shiro自定义Realm

不念不忘少年蓝@ 2022-11-25 13:03 432阅读 0赞

三、SpringBoot整合Shiro完成权限管理案例—自定义Realm

使用JdbcRealm可以完成用户权限管理,但是我们必须提供JdbcRealm规定的数据表结构;如果在我们的项目开发中 ,这个JdbcRealm规定的数据表结构不能满足开发需求,该如何处理呢?

  • 自定义数据库表结构
  • 自定义Realm实现认证和授权











 
 

3.1 数据库设计

  • RBAC基于角色的访问控制

    1. -- 用户信息表
    2. create table tb_users(
    3. user_id int primary key auto_increment,
    4. username varchar(60) not null unique,
    5. password varchar(20) not null,
    6. password_salt varchar(60)
    7. );
    8. insert into tb_users(username,password) values('zhangsan','123456');
    9. insert into tb_users(username,password) values('lisi','123456');
    10. insert into tb_users(username,password) values('wangwu','123456');
    11. insert into tb_users(username,password) values('zhaoliu','123456');
    12. insert into tb_users(username,password) values('chenqi','123456');
    13. -- 角色信息表
    14. create table tb_roles(
    15. role_id int primary key auto_increment,
    16. role_name varchar(60) not null
    17. );
    18. insert into tb_roles(role_name) values('admin');
    19. insert into tb_roles(role_name) values('cmanager'); -- 仓管
    20. insert into tb_roles(role_name) values('xmanager'); -- 销售
    21. insert into tb_roles(role_name) values('kmanager'); -- 客服
    22. insert into tb_roles(role_name) values('zmanager'); -- 行政
    23. -- 权限信息表
    24. create table tb_permissions(
    25. permission_id int primary key auto_increment, -- 1
    26. permission_code varchar(60) not null, -- sys:c:find
    27. permission_name varchar(60) -- 仓库查询
    28. );
    29. insert into tb_permissions(permission_code,permission_name) values('sys:c:save','入库');
    30. insert into tb_permissions(permission_code,permission_name) values('sys:c:delete','出库');
    31. insert into tb_permissions(permission_code,permission_name) values('sys:c:update','修改');
    32. insert into tb_permissions(permission_code,permission_name) values('sys:c:find','查询');
    33. insert into tb_permissions(permission_code,permission_name) values('sys:x:save','新增订单');
    34. insert into tb_permissions(permission_code,permission_name) values('sys:x:delete','删除订单');
    35. insert into tb_permissions(permission_code,permission_name) values('sys:x:update','修改订单');
    36. insert into tb_permissions(permission_code,permission_name) values('sys:x:find','查询订单');
    37. insert into tb_permissions(permission_code,permission_name) values('sys:k:save','新增客户');
    38. insert into tb_permissions(permission_code,permission_name) values('sys:k:delete','删除客户');
    39. insert into tb_permissions(permission_code,permission_name) values('sys:k:update','修改客户');
    40. insert into tb_permissions(permission_code,permission_name) values('sys:k:find','查询客户');
    41. -- 用户角色表
    42. create table tb_urs(
    43. uid int not null,
    44. rid int not null
    45. -- primary key(uid,rid),
    46. -- constraint FK_user foreign key(uid) references tb_users(user_id),
    47. -- constraint FK_role foreign key(rid) references tb_roles(role_id)
    48. );
    49. insert into tb_urs(uid,rid) values(1,1);
    50. insert into tb_urs(uid,rid) values(1,2);
    51. insert into tb_urs(uid,rid) values(1,3);
    52. insert into tb_urs(uid,rid) values(1,4);
    53. insert into tb_urs(uid,rid) values(1,5);
    54. insert into tb_urs(uid,rid) values(2,2);
    55. insert into tb_urs(uid,rid) values(3,3);
    56. insert into tb_urs(uid,rid) values(4,4);
    57. insert into tb_urs(uid,rid) values(5,5);
    58. -- 角色权限表
    59. create table tb_rps(
    60. rid int not null,
    61. pid int not null
    62. );
    63. -- 给仓管角色分配权限
    64. insert into tb_rps(rid,pid) values(2,1);
    65. insert into tb_rps(rid,pid) values(2,2);
    66. insert into tb_rps(rid,pid) values(2,3);
    67. insert into tb_rps(rid,pid) values(2,4);
    68. -- 给销售角色分配权限
    69. insert into tb_rps(rid,pid) values(3,4);
    70. insert into tb_rps(rid,pid) values(3,5);
    71. insert into tb_rps(rid,pid) values(3,6);
    72. insert into tb_rps(rid,pid) values(3,7);
    73. insert into tb_rps(rid,pid) values(3,8);
    74. insert into tb_rps(rid,pid) values(3,9);
    75. insert into tb_rps(rid,pid) values(3,10);
    76. insert into tb_rps(rid,pid) values(3,11);
    77. insert into tb_rps(rid,pid) values(3,12);
    78. -- 给客服角色分配权限
    79. insert into tb_rps(rid,pid) values(4,11);
    80. insert into tb_rps(rid,pid) values(4,12);
    81. -- 给行政角色分配权限
    82. insert into tb_rps(rid,pid) values(5,4);
    83. insert into tb_rps(rid,pid) values(5,8);
    84. insert into tb_rps(rid,pid) values(5,12);

3.2 DAO实现

  • Shiro进行认证需要用户信息:

    • 根据用户名查询用户信息
  • Shiro进行授权管理需要当前用户的角色和权限

    • 根据用户名查询当前用户的角色列表(3张表连接查询)
    • 根据用户名查询当前用户的权限列表(5张表连接查询)

3.2.1 创建SpringBoot项目,整合MyBatis

3.2.2 根据用户名查询用户信息

  • 创建BeanBean

    @Data
    public class User {

    1. private Integer userId;
    2. private String userName;
    3. private String userPwd;
    4. private String pwdSalt;

    }

  • 创建DAO

    public interface UserDAO {

    1. public User queryUserByUsername(String username) throws Exception;

    }

  • 映射配置

    <?xml version=”1.0” encoding=”UTF-8” ?>
    <!DOCTYPE mapper

    1. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    2. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">











3.2.3 根据用户名查询角色名列表

  • 创建DAO

    public interface RoleDAO {

    1. public Set<String> queryRoleNamesByUsername(String username) throws Exception;

    }

  • 映射配置

    <?xml version=”1.0” encoding=”UTF-8” ?>
    <!DOCTYPE mapper

    1. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    2. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">




3.2.4 根据用户名查询权限列表

  • 创建DAO

    public interface PermissionDAO {

    1. public Set<String> queryPermissionsByUsername(String username) throws Exception;

    }

  • 映射配置

    <?xml version=”1.0” encoding=”UTF-8” ?>
    <!DOCTYPE mapper

    1. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    2. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">




3.3 整合Shiro

  • 导入依赖


    org.apache.shiro
    shiro-spring
    1.4.1


    com.github.theborakompanioni
    thymeleaf-extras-shiro
    2.0.0
  • 配置Shiro-基于Java配置方式

    @Configuration
    public class ShiroConfig {

    1. @Bean
    2. public ShiroDialect getShiroDialect(){
    3. return new ShiroDialect();
    4. }

    1. //自定义Realm
    2. @Bean
    3. public MyRealm getMyRealm(){
    4. MyRealm myRealm = new MyRealm();
    5. return myRealm;
    6. }

    1. @Bean
    2. public DefaultWebSecurityManager getDefaultWebSecurityManager(MyRealm myRealm){
    3. DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    4. securityManager.setRealm(myRealm);
    5. return securityManager;
    6. }

    1. @Bean
    2. public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager){
    3. ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
    4. //过滤器就是shiro就行权限校验的核心,进行认证和授权是需要SecurityManager的
    5. filter.setSecurityManager(securityManager);

    1. Map<String,String> filterMap = new HashMap<>();
    2. filterMap.put("/","anon");
    3. filterMap.put("/index.html","anon");
    4. filterMap.put("/login.html","anon");
    5. filterMap.put("/regist.html","anon");
    6. filterMap.put("/user/login","anon");
    7. filterMap.put("/user/regist","anon");
    8. filterMap.put("/layui/**","anon");
    9. filterMap.put("/**","authc");

    1. filter.setFilterChainDefinitionMap(filterMap);
    2. filter.setLoginUrl("/login.html");
    3. //设置未授权访问的页面路径()
    4. filter.setUnauthorizedUrl("/login.html");
    5. return filter;
    6. }


    }

  • 自定义Realm

    /**

    • 1.创建一个类继承AuthorizingRealm类(实现了Realm接口的类)
    • 2.重写doGetAuthorizationInfo和doGetAuthenticationInfo方法
    • 3.重写getName方法返回当前realm的一个自定义名称
      */
      public class MyRealm extends AuthorizingRealm {

      @Resource
      private UserDAO userDAO;
      @Resource
      private RoleDAO roleDAO;
      @Resource
      private PermissionDAO permissionDAO;

      public String getName() {

      1. return "myRealm";

      }

      /**

      • 获取授权数据(将当前用户的角色及权限信息查询出来)
        /
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取用户的用户名
        String username = (String) principalCollection.iterator().next();
        //根据用户名查询当前用户的角色列表
        Set roleNames = roleDAO.queryRoleNamesByUsername(username);
        //根据用户名查询当前用户的权限列表
        Set ps = permissionDAO.queryPermissionsByUsername(username);

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setRoles(roleNames);
        info.setStringPermissions(ps);
        return info;
        }

        /*
      • 获取认证的安全数据(从数据库查询的用户的正确数据)
        */
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //参数authenticationToken就是传递的 subject.login(token)
        // 从token中获取用户名
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String username = token.getUsername();
        //根据用户名,从数据库查询当前用户的安全数据
        User user = userDAO.queryUserByUsername(username);

        AuthenticationInfo info = new SimpleAuthenticationInfo(
        1. username, //当前用户用户名,对应doGetAuthorizationInfo中的PrincipalCollection
        2. user.getUserPwd(), //从数据库查询出来的安全密码
        3. getName());

        return info;
        }
        }

发表评论

表情:
评论列表 (有 0 条评论,432人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Shiro定义Realms

    Shiro 的三个核心组件:Subject, SecurityManager 和 Realms. 来回顾一下这三个组件的关系 ![Shiro 的三个核心组件][Shiro]