展开
拓展 关闭
订阅号推广码
GitHub
视频
公告栏 关闭

身份授权

  • 简介
1、首先调用Subject.isPermitted/hasRole接口,其会委托给SecurityManager
2、SecurityManager接着会委托给内部组件Authorizer
3、Authorizer再将其请求委托给我们的Realm去做;Realm才是真正干活的
4、Realm将用户请求的参数封装成权限对象。再从我们重写的doGetAuthorizationInfo方法中获取从数据库中查询到的权限集合
5、Realm将用户传入的权限对象,与从数据库中查出来的权限对象,进行一一对比。如果用户传入的权限对象在从数据库中查出来的权限对象中,则返回true,否则返回false

进行授权操作的前提:用户必须通过认证
  • 模拟从数据库中查询到的用户权限
public interface SecurityService {

    /**
     * @Description 查找用户密码
     * @param loginName 用户名称
     * @return 密码
     */
    Map<String,String> findPasswordByLoginName(String loginName);

    /**
     * @Description 查询角色
     * @param loginName 用户名
     * @return 角色字符串列表
     */
    List<String> findRoleByLoginName(String loginName);

    /**
     * @Description 查询资源
     * @param loginName 用户名
     * @return 资源字符串列表
     */
    List<String> findPermissionByLoginName(String loginName);
}
  • 具体实现
public class SecurityServiceImpl implements SecurityService {

    @Override
    public Map<String,String> findPasswordByLoginName(String loginName) {
        return DigestsUtil.entryptPassword("123");
    }

    @Override
    public List<String> findRoleByLoginName(String loginName) {
        List<String> list = new ArrayList<>();
        list.add("admin");
        list.add("dev");
        return list;
    }

    @Override
    public List<String> findPermissionByLoginName(String loginName) {
        List<String> list = new ArrayList<>();
        list.add("order:add");
        list.add("order:list");
        list.add("order:del");
        return list;
    }
}
  • 实现鉴权方法
public class DefinitionRealm extends AuthorizingRealm {

    public DefinitionRealm() {
        //指定密码匹配方式sha1
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(DigestsUtil.SHA1);
        //指定密码迭代次数
        hashedCredentialsMatcher.setHashIterations(DigestsUtil.ITERATIONS);
        //使用父层方法是匹配方式生效
        setCredentialsMatcher(hashedCredentialsMatcher);
    }

    /**
     * @Description 认证方法
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //获取登录名
        String loginName = (String) authenticationToken.getPrincipal();
        SecurityService securityService = new SecurityServiceImpl();
        Map<String, String> map = securityService.findPasswordByLoginName(loginName);
        if(map.isEmpty()){
            throw new UnknownAccountException("账户不存在");
        }
        String salt = map.get("salt");
        String password = map.get("password");
        return new SimpleAuthenticationInfo(loginName,password, ByteSource.Util.bytes(salt),getName());
    }

    /**
     * @Description 鉴权方法
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //拿到用户凭证信息
        String loginName = (String) principalCollection.getPrimaryPrincipal();
        //从数据库中查询对应的角色和权限
        SecurityService securityService = new SecurityServiceImpl();
        List<String> roles = securityService.findRoleByLoginName(loginName);
        List<String> permissions = securityService.findPermissionByLoginName(loginName);
        //构建资源校验对象
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.addRoles(roles);
        simpleAuthorizationInfo.addStringPermissions(permissions);
        return simpleAuthorizationInfo;
    }

}
  • 测试
public class HelloShiro {

    @Test
    public void testPermissionRealm(){
        Subject subject = shiroLogin();
        //打印登录信息
        System.out.println("登录结果:"+subject.isAuthenticated());
        //-------校验当前用户是否拥有管理员的角色
        System.out.println("是否有管理员角色"+subject.hasRole("admin"));
        //-------校验当前用户没有的角色
        try {
            subject.checkRole("coder");
            System.out.println("当前用户有coder角色");
        }catch (Exception ex){
            System.out.println("当前用户没有coder角色");
        }
        //-------校验当前用户的权限信息
        System.out.println("是否有查看订单的权限"+subject.isPermitted("order:list"));
        //-------校验当前用户满意的权限
        try {
            subject.checkPermission("order:update");
            System.out.println("当前用户有修改的权限");
        }catch (Exception ex){
            System.out.println("当前用户没有修改的权限");
        }
    }

    public Subject shiroLogin(){
        //导入INI配置创建工厂
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        //工厂构建安全管理器
        SecurityManager securityManager = factory.getInstance();
        //使用工具生效安全管理器
        SecurityUtils.setSecurityManager(securityManager);
        //使用工具获得subject主体
        Subject subject = SecurityUtils.getSubject();
        //构建账户密码
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("jay","123");
        //使用subject主体去登录
        subject.login(usernamePasswordToken);
        return subject;
    }

}
  • 控制台
登录结果:true
是否有管理员角色true
当前用户没有coder角色
是否有查看订单的权限true
当前用户没有修改的权限
posted @ 2022-09-05 11:32  DogLeftover  阅读(18)  评论(0编辑  收藏  举报