Spring Boot 使用 JdbcRealm 进行认证授权(四)

概述

上一篇博客我们主要讲了把用户安全信息(相应的角色/权限)配置在 .ini 文件,使用 IniRealm 去读取 .ini 文件获得用户的安全信息。也是有局限性的。因为我们得事先把所有用户信息配置在.ini 文件,这样显然是行不通的,我们的系统用户都是动态的不固定的,它的一些用户信息权限信息都是变化的,所以固定在.ini 配置文件显然是行不通的。这些数据通常我们都是把它存入到DB 中,那shiro 有没有提供直接从DB读取用户安全信息的域呢 ? (Realm)

shiro 作为一个优秀的开源框架,显然是可以的。

下面就该 JdbcRealm 出场了。

JdbcRealm 实践

JdbcRealm 实践

很明显看到 jdbc 就明白是跟数据有关的吧,所以我们要引入 mysql 数据库驱动

      <!--数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

数据源

有了mysql数据库驱动是不是得加个数据源呀?这里我们用阿里的druid

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>

数据库表结构

下面我们创建一个名为 shiro 的数据库、分别创建三张表 users、user_roles、roles_permissions

CREATE DATABASE IF NOT EXISTS shiro DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
  • users
CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(25) DEFAULT NULL,
  `password` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • roles_permissions
CREATE TABLE `roles_permissions` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `permission` varchar(255) DEFAULT NULL,
  `role_name` varchar(25) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • user_roles
CREATE TABLE `user_roles` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `role_name` varchar(25) DEFAULT NULL,
  `username` varchar(25) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • 分别插入如下几条数据
USE shiro;
INSERT INTO `shiro`.`users` (`id`, `username`, `password`) VALUES ('1', 'admin', '123456');
INSERT INTO `shiro`.`users` (`id`, `username`, `password`) VALUES ('2', 'test', '123456');
INSERT INTO `shiro`.`user_roles` (`id`, `role_name`, `username`) VALUES ('1', 'admin', 'admin');
INSERT INTO `shiro`.`user_roles` (`id`, `role_name`, `username`) VALUES ('2', 'test', 'test');
INSERT INTO `shiro`.`roles_permissions` (`id`, `permission`, `role_name`) VALUES ('1', 
'user:deleted', 'test');
INSERT INTO `shiro`.`roles_permissions` (`id`, `permission`, `role_name`) VALUES ('2', 
'user:list', 'test');
INSERT INTO `shiro`.`roles_permissions` (`id`, `permission`, `role_name`) VALUES ('3', '*', 
'admin');
INSERT INTO `shiro`.`roles_permissions` (`id`, `permission`, `role_name`) VALUES ('4', 
'user:edit', 'test');

创建 testJdbcRealm方法

@Test
    public void testJdbcRealm(){
        //配置数据源
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl("jdbc:mysql://localhost:3306/shiro");
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUsername("root");
        dataSource.setPassword("123456");
        //配置文件中的用户权限信息,文件在类路径下
        JdbcRealm jdbcRealm = new JdbcRealm();
        jdbcRealm.setDataSource(dataSource);
        //使用JdbcRealm下面的值需要为true不然无法查询用户权限
        jdbcRealm.setPermissionsLookupEnabled(true);
        //1,构建SecurityManager环境
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //设置Realm
        defaultSecurityManager.setRealm(jdbcRealm);

        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");
            System.out.println("有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 登录进来的时候 程序输出

认证状态:isAuthenticated=true
有admin角色
有user:delete权限

当用户 test 登录进来的时候 程序输出

UsernamePasswordToken token = new UsernamePasswordToken("test", "123456");
认证状态:isAuthenticated=true
用户没有权限

源码分析

看了这个例子,为什么我们没有写 sql 怎么查询用户信息和角色,权限信息的呢?我们来看JdbcRealm源码
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
从以上源码得知其实 JdbcRealm 已经帮我们写好查询语句了,所以我们就要在数据库创建与之对应的表结构,这样才能查出数据,但是有的同学可能就有疑问了,这里只能使用他默认的 sql,在实际的开发中,我们不可能就简单的使用 JdbcRealm 默认的 sql 语句,而是自己自定义的 sql 语句,更多时候我们的数据库以及数据表都是根据业务需要自己创建的。

  • 首先把上面三张表分别修改一下表名
USE shiro;
ALTER TABLE users RENAME sys_users;
ALTER TABLE user_roles RENAME sys_user_roles;
ALTER TABLE roles_permissions RENAME sys_roles_permissions;

在这里插入图片描述

新建testNewJdbcRealm

@Test
    public void testNewJdbcRealm(){
        //配置数据源
        DruidDataSource dataSource = new DruidDataSource();
        //如果使用的是新版的驱动 配置driver的时候要注意
        dataSource.setUrl("jdbc:mysql://localhost:3306/shiro?serverTimezone=UTC");
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        //配置文件中的用户权限信息,文件在类路径下
        JdbcRealm jdbcRealm = new JdbcRealm();
        jdbcRealm.setDataSource(dataSource);
        //使用JdbcRealm下面的值需要为true不然无法查询用户权限
        jdbcRealm.setPermissionsLookupEnabled(true);
        //使用自定义sql查询用户信息
        String sql="select password from sys_users where username = ?";
        jdbcRealm.setAuthenticationQuery(sql);
        String roleSql = "select role_name from sys_user_roles where username = ?";
        jdbcRealm.setUserRolesQuery(roleSql);
        String permissionsSql = "select permission from sys_roles_permissions where role_name = ?";
        jdbcRealm.setPermissionsQuery(permissionsSql);
        //1,构建SecurityManager环境
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //设置Realm
        defaultSecurityManager.setRealm(jdbcRealm);

        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("用户没有权限");
        }
    }
  • 最后程序输出
认证状态:isAuthenticated=true
有admin角色
有 user:add、user:list、user:edit、user:delete权限
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一名技术极客

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

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

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

打赏作者

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

抵扣说明:

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

余额充值