Shiro自定义权限验证


[参考]( (1条消息) Shiro 学习笔记(5)—— 自定义权限解析器和角色解析器_李威威的博客-CSDN博客_shiro 自定义权限)

背景

项目里面接口权限设计格式是METHOD:URL

对于带参的URL,其权限字符串会如GET:/api/permission/find/{id},Shiro默认是以冒号为分隔对每一段进行匹配,所以前端发起相应请求,后端组成的权限字符串GET:/api/permission/find/1不会被Shrio识别为与GET:/api/permission/find/{id}相同的权限

因此需要自定义权限认证进行匹配

解决方案

通过定义一个权限类实现 Permission 中的 implies(Permission permission) 方法来实现自定义权限认证。

在匹配时将 GET:/api/permission/find/{id} 切割为 GET:/api/permission/find/ ,然后调用 GET:/api/permission/find/1startsWith方法进行匹配

PermissionCheckModel.java

权限类,定义权限匹配方法:

/**
 * @Description 自定义权限字符串比较
 * @Author 王星宇
 * @Date 2021-11-06
 * @Version 1.0
 **/
public class PermissionCheckModel implements Permission , Serializable {

    private String permissionStr;
    
    public PermissionCheckModel(){}

    public PermissionCheckModel(String perissionStr){
        this.permissionStr = perissionStr;
    }

    /**
     * 传进来的 GET:/api/permission/find/1 与 GET:/api/permission/find/{id} 进行比较
     * @param permission  GET:/api/permission/find/1
     * @return
     */
    @Override
    public boolean implies(Permission permission) {
        if(!(permission instanceof PermissionCheckModel)){
            return false;
        }
        String permissionHave = permissionStr;
        if(permissionHave.indexOf("{") > 1){
            permissionHave = permissionHave.substring(0,permissionHave.indexOf("{"));
        }
        PermissionCheckModel model = (PermissionCheckModel)permission;
        if(model.permissionStr.startsWith(permissionHave)){
            return true;
        }
        return false;
    }
}

MyPermissionResolver.java

根据传入的权限字符串选择不同的权限类,这里全部使用上面定义的 PermissionCheckModel.java

/**
 * @Description 根据不同的接口选择使用不同的resolver
 * @Author 王星宇
 * @Date 2021-11-06
 * @Version 1.0
 **/
public class MyPermissionResolver implements PermissionResolver {
    @Override
    public Permission resolvePermission(String s) {
        return new PermissionCheckModel(s);
    }
}

ShiroConfig.java

在Shiro的配置类中配置使用定义的 MyPermissionResolver.java

@Bean
public MyPermissionResolver myPermissionResolver(){
    return new MyPermissionResolver();
}

@Bean
public Realm getRealm(MyPermissionResolver myPermissionResolver){
    CustomerRealm customerRealm = new CustomerRealm();
    HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
    credentialsMatcher.setHashAlgorithmName("SHA");

    customerRealm.setCachingEnabled(true);
    customerRealm.setAuthenticationCachingEnabled(true);
    customerRealm.setAuthorizationCachingEnabled(true);
    customerRealm.setCacheManager(new RedisCacheManager());
    customerRealm.setPermissionResolver(myPermissionResolver); // 使用自定义的Resolver
    return customerRealm;
}

CustomerRealm.java

为用户设置权限时设置定义的 PermissionCheckModel.java 权限类

public class CustomerRealm extends AuthorizingRealm {

    Logger logger = LoggerFactory.getLogger(CustomerRealm.class);

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 查询出用户权限
        List<String> permissions = ;
        for(String permission : permissions){
            if(permission != null) {
                // 为用户设置权限
                info.addObjectPermission(new PermissionCheckModel(permission));
            }
        }
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
		// 认证操作
    }
}

版权声明:本文为w_xy999原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。