Spring Boot 使用自定义 Realm 进行认证授权(五)

Spring Boot 使用自定义 Realm 进行认证授权

概述

虽然 jdbcRealm 已经实现了从数据库中获取用户的验证信息,但是jdbcRealm灵活性也是稍差一些的,如果要实现自己的一些特殊应用时将不能支持,这个时候可以通过自定义realm来实现身份的认证功能。

通常自定义Realm只需要继承:AuthorizingRealm重写doGetAuthenticationInfo(用户认证)、doGetAuthorizationInfo(用户授权) 这两个方法即可。

自定义 Realm

创建 CustomRealm

public class CustomRealm extends AuthorizingRealm {

    /**
     * 模拟数据库中的用户名和密码
     */
    private Map<String, String> userMap = new HashMap<>();

    /**
     * 使用代码块初始化数据
     */ {
        userMap.put("admin", "123456");
        userMap.put("test", "123456");
    }

    /**
     * 用户授权
     *
     * @param principalCollection
     * @return org.apache.shiro.authz.AuthorizationInfo
     * @throws
     * @Author: djy
     * @UpdateUser:
     * @Version: 0.0.1
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //这个就是SimpleAuthenticationInfo(username,password,getName()); 第一个参数
//        String username= (String) SecurityUtils.getSubject().getPrincipal();
        System.out.println("开始执行*******doGetAuthorizationInfo方法啦****");
        System.out.println(SecurityUtils.getSubject().getPrincipal());
        String username = (String) principalCollection.getPrimaryPrincipal();
        //从数据库或者缓存中获取角色数据
        List<String> roles = getRolesByUsername(username);
        //从数据库或者缓存中获取权限数据
        List<String> permissions = getPerminssionsByUsername(username);
        //创建AuthorizationInfo,并设置角色和权限信息
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.addStringPermissions(permissions);
        authorizationInfo.addRoles(roles);
        return authorizationInfo;
    }

    /**
     * 用户认证
     *
     * @param authenticationToken
     * @return org.apache.shiro.authc.AuthenticationInfo
     * @throws
     * @Author: djy
     * @UpdateUser:
     * @Version: 0.0.1
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("开始执行*******doGetAuthenticationInfo方法啦****");
        //获取登录用户名
        String userName = (String) authenticationToken.getPrincipal();
        //通过用户名到数据库获取用户信息
        String password = getPasswordByUsername(userName);
        if (null == password) {
            return null;
        }
        System.out.println("密码为:" + password);
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(userName, password, getName());
        return authenticationInfo;
    }


    /**
     * 模拟通过数据库获取权限数据
     *
     * @param username
     * @return java.util.List<java.lang.String>
     * @throws
     * @Author: djy
     * @UpdateUser:
     * @Version: 0.0.1
     */
    private List<String> getPerminssionsByUsername(String username) {
        List<String> permissions = new ArrayList<>();
        /**
         * 只有是 admin 用户才有 新增、删除权限
         */
        if (username.equals("admin")) {
            permissions.add("user:delete");
            permissions.add("user:add");
        }
        permissions.add("user:edit");
        permissions.add("user:list");
        return permissions;
    }

    /**
     * 模拟通过数据库获取用户角色信息
     *
     * @param username
     * @return java.util.List<java.lang.String>
     * @throws
     * @Author: djy
     * @UpdateUser:
     * @Version: 0.0.1
     */
    private List<String> getRolesByUsername(String username) {
        List<String> roles = new ArrayList<>();
        if (username.equals("admin")) {
            roles.add("admin");
        }
        roles.add("test");
        return roles;
    }

    /**
     * 通过用户名查询密码,模拟数据库查询
     *
     * @param userName
     * @return java.lang.String
     * @throws
     * @Author: djy
     * @UpdateUser:
     * @Version: 0.0.1
     */
    private String getPasswordByUsername(String userName) {
        return userMap.get(userName);
    }

创建 testCustomRealm 方法

    @Test
    public void testCustomRealm() {
        CustomRealm customRealm = new CustomRealm();
        //1,构建SecurityManager环境
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //设置Realm
        defaultSecurityManager.setRealm(customRealm);
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //获取主体
        Subject subject = SecurityUtils.getSubject();
        //用户名和密码的token
        UsernamePasswordToken token = new UsernamePasswordToken("admin", "123456");
        try {
            //2,主体提交认证请求
            subject.login(token);
            System.out.println("认证状态:isAuthenticated=" + subject.isAuthenticated());
            //检查是否有角色
            subject.checkRoles("admin");
            System.out.println("有admin角色");
            //检查是否有权限
            subject.checkPermissions("user:delete", "user:edit", "user:list", "user:add");
            System.out.println("有 user:add、user:list、user:edit、user:delete权限");
        } catch (IncorrectCredentialsException exception) {
            System.out.println("用户名或密码错误");
        } catch (LockedAccountException exception) {
            System.out.println("账号已被锁定");
        } catch (DisabledAccountException exception) {
            System.out.println("账号已被禁用");
        } catch (UnknownAccountException exception) {
            System.out.println("用户不存在");
        } catch (UnauthorizedException ae) {
            System.out.println("用户没有权限");
        }
    }

测试

  • 当用户 admin 登录进来的时候 程序输出
UsernamePasswordToken token = new UsernamePasswordToken("admin", "123456");

在这里插入图片描述

  • 当用户 test 登录进来的时候 程序输出
UsernamePasswordToken token = new UsernamePasswordToken("test", "123456");

在这里插入图片描述

  • 当用户 dev 登陆进来的时候 程序输出
UsernamePasswordToken token = new UsernamePasswordToken("dev", "123456");

在这里插入图片描述

通过上述验证过程我们可以发现,shiro 更多的是帮助我们完成验证过程。我们需要从数据库查询当前用户的角色、权限,把这些信息告诉shiro框架。当我们执行用户认证的时候首先调用 doGetAuthenticationInfo进行用户认证,当我们要校验权限的时候 就会执行
doGetAuthorizationInfo 进行授权操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一名技术极客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值