美文网首页工作专题java学习
Spring Boot 集成 Shiro权限框架

Spring Boot 集成 Shiro权限框架

作者: LeonardoEzio | 来源:发表于2018-04-24 22:58 被阅读1006次

    一、新建SpringBoot项目

    添加SpringBoot相关依赖
     <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
    
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    

    二、添加Shiro依赖

      <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
     </dependency>
    

    三、建立权限相关表(五表权限设计)

     create table user(
     id int NOT NULL PRIMARY KEY AUTO_INCREMENT,
     username VARCHAR(20) NOT NULL ,
     password VARCHAR(20) not null
    );
    
    create table role(
    id int NOT NULL PRIMARY KEY AUTO_INCREMENT,
    rolename VARCHAR(20) NOT NULL,
    roledesc VARCHAR(20)
    );
    
    
    create table permission(
    id int NOT NULL PRIMARY KEY AUTO_INCREMENT,
    modelname VARCHAR(20) NOT NULL ,
    permission VARCHAR(20) NOT NULL
    );
    
    create table user_role(
    id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    uid int NOT NULL ,
    rid int NOT NULL
    );
    
    
    create table role_permission(
    id INT NOT NULL  PRIMARY KEY  AUTO_INCREMENT,
    rid int NOT NULL ,
    pid int NOT NULL
    );
    

    四、Shiro配置

    @Configuration
    public class ShiroConfig {
    
        public ShiroConfig(){
             System.out.println("ShiroConfig  init ....");
        }
    
         /**
          shiro过滤器配置
        */
        @Bean
        public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
            System.out.println("ShiroConfiguration.shirFilter()");
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            //拦截器.
            Map<String,String> filterChainDefinitionMap = new  LinkedHashMap<String,String>();
            //权限配置
            //filterChainDefinitionMap.put("/stu/addStu","perms[student:aaaa]");
            // 配置不会被拦截的链接 顺序判断  相关静态资源
            filterChainDefinitionMap.put("/assets/**", "anon");
            filterChainDefinitionMap.put("/css/**", "anon");
            filterChainDefinitionMap.put("/font/**", "anon");
            filterChainDefinitionMap.put("/images/**", "anon");
            filterChainDefinitionMap.put("/js/**", "anon");
            filterChainDefinitionMap.put("/products/**", "anon");
            filterChainDefinitionMap.put("/Widget/**", "anon");
    
            //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
            filterChainDefinitionMap.put("/logout", "logout");
    
            //<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
    
            //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
            filterChainDefinitionMap.put("/**", "authc");
            // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
            shiroFilterFactoryBean.setLoginUrl("/login");
            // 登录成功后要跳转的链接
            shiroFilterFactoryBean.setSuccessUrl("/index");
    
            //未授权界面;
            shiroFilterFactoryBean.setUnauthorizedUrl("/403");
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
            return shiroFilterFactoryBean;
        }
        /*
        加密方式配置
        */
        @Bean
        public HashedCredentialsMatcher hashedCredentialsMatcher(){
            HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
            hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
            hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5(""));
            return hashedCredentialsMatcher;
        }
    
          /*
          认证器配置
          */
        @Bean
        public MyShiroRelam myShiroRealm(){
            MyShiroRelam myShiroRelam = new MyShiroRelam();
            //myShiroRelam.setCredentialsMatcher(hashedCredentialsMatcher());
            return myShiroRelam;
        }
    
        /*
        安全管理器配置
        */
        @Bean
        public SecurityManager securityManager(){
            DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
            securityManager.setRealm(myShiroRealm());
             return securityManager;
        }
    
        /*
        开启@RequirePermission注解的配置,要结合DefaultAdvisorAutoProxyCreator一起使用,或者导入aop的依赖
        */
        @Bean
        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
            AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
            authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
            return authorizationAttributeSourceAdvisor;
        }
    
        /* @Bean
        public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
              DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
              advisorAutoProxyCreator.setProxyTargetClass(true);
              return advisorAutoProxyCreator;
        }*/
    
    
        /*
        定义Spring MVC的异常处理器
        */
        @Bean
        public SimpleMappingExceptionResolver createSimpleMappingExceptionResolver() {
            SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
            Properties mappings = new Properties();
            mappings.setProperty("DatabaseException", "databaseError");//数据库异常处理
            mappings.setProperty("UnauthorizedException","403");//处理shiro的认证未通过异常
            r.setExceptionMappings(mappings);  // None by default
            r.setDefaultErrorView("error");    // No default
            r.setExceptionAttribute("ex");     // Default is "exception"
            return r;
        }
    }
    

    五、定义类继承AuthorizingRealm主要用来做登录验证和权限分配

    public class MyShiroRelam extends AuthorizingRealm {
    
        @Autowired
        private IUserService userService;
    
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            System.out.println("用户权限配置。。。。。。。。。。");
            //访问@RequirePermission注解的url时触发
            SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
            User userInfo  = (User)principals.getPrimaryPrincipal();
            //获得用户的角色,及权限进行绑定
            for(Role role:userInfo.getRoleList()){
                authorizationInfo.addRole(role.getRolename());
                for(Permission p:role.getPermissions()){
                    authorizationInfo.addStringPermission(p.getPermission());
                }
            }
            return authorizationInfo;
        }
    
        //验证用户登录信息
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            System.out.println("验证用户登录信息");
            String username = (String)token.getPrincipal();
            System.out.println("登录用户名: "+username);
            System.out.println(token.getCredentials());
           //从数据库查询出User信息及用户关联的角色,权限信息,以备权限分配时使用
            User user = userService.findUserByName(username);
            if(null == user) return null;
            System.out.println("username: "+user.getUsername()+" ; password : "+user.getPassword());
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                user, //用户名
                user.getPassword(), //密码
                getName()  //realm name
           );
            return authenticationInfo;
        }
    }
    

    六、实体类

    public class User {
        private int id;
        private String username;
        private String password;
    
        //用户的角色   一对多关系
        private List<Role> roleList;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public List<Role> getRoleList() {
            return roleList;
        }
    
        public void setRoleList(List<Role> roleList) {
            this.roleList = roleList;
        }
    }
    
    
    
    public class Role {
    
        private int id;
        private String rolename;//角色名称
        private String roledesc;//角色描述
    
        private List<Permission> permissions;//角色权限关系  多对多  一个角色对应多个权限
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getRolename() {
            return rolename;
        }
    
        public void setRolename(String rolename) {
            this.rolename = rolename;
        }
    
        public String getRoledesc() {
            return roledesc;
        }
    
        public void setRoledesc(String roledesc) {
            this.roledesc = roledesc;
        }
    
        public List<Permission> getPermissions() {
            return permissions;
        }
    
        public void setPermissions(List<Permission> permissions) {
            this.permissions = permissions;
        }
    }
    
    
    
    public class Permission {
        private int id;
        private String modelname;
        private String permission;
    
        private List<Role> roles;//角色权限关系   多对多
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getModelname() {
            return modelname;
        }
    
        public void setModelname(String modelname) {
            this.modelname = modelname;
        }
    
        public String getPermission() {
            return permission;
        }
    
        public void setPermission(String permission) {
            this.permission = permission;
        }
    
        public List<Role> getRoles() {
            return roles;
        }
    
        public void setRoles(List<Role> roles) {
            this.roles = roles;
        }
    }
    

    七、UserService接口编写

    public interface IUserService {
        public User findUserByName(String name);
    }
    
    
    @Service
    public class UserServiceImpl implements IUserService {
    
        @Autowired
        private IUserDao userDao;
    
        @Override
        public User findUserByName(String name) {
            return userDao.findUserByName(name);
        }
    }
    

    八、UserDao接口编写

    @Repository
    @Mapper
    public interface IUserDao {
        public User findUserByName(String name);
    }
    
    UserDao.xml文件的编写
     <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="leonardo.ezio.permission.demo.shiro.dao.IUserDao">
    <select id="findUserByName" parameterType="String" resultMap="user" >
        select u.id u_id,username,password,r.id r_id ,rolename ,roledesc , p.id p_id ,modelname,permission from user u
        INNER JOIN user_role ur on u.id = ur.uid
        INNER JOIN role r ON ur.rid = r.id
        INNER JOIN role_permission rp ON r.id = rp.rid
        INNER JOIN permission p on rp.pid = p.id
        where u.username = #{name}
    </select>
    
    <resultMap id="user" type="leonardo.ezio.permission.demo.shiro.bean.User">
        <id property="id" column="u_id"></id>
        <result property="username" column="username"/>
        <result property="password" column="password"/>
        <collection property="roleList" ofType="leonardo.ezio.permission.demo.shiro.bean.Role">
            <id property="id" column="r_id"/>
            <result property="rolename" column="rolename"/>
            <result property="roledesc" column="roledesc"/>
            <collection property="permissions" ofType="leonardo.ezio.permission.demo.shiro.bean.Permission">
                <id property="id" column="p_id"/>
                <result property="modelname" column="modelname"/>
                <result property="permission" column="permission"/>
            </collection>
        </collection>
    </resultMap>
    </mapper>
    

    九、Controller的编写

    @Controller
    public class HomeController {
    
        @Autowired
        private IUserService userService;
    
        @RequestMapping({"/","/index"})
        public String root(){
            return "index";
        }
    
        @RequestMapping("/login")
        public String login(HttpServletRequest request, Map<String ,String> map){
            System.out.println("user login .....");
            String exception = (String) request.getAttribute("shiroLoginFailure");
            System.out.println("exception=" + exception);
            String msg = "";
            if (exception != null) {
                if (UnknownAccountException.class.getName().equals(exception)) {
                    System.out.println("UnknownAccountException -- > 账号不存在:");
                    msg = "unknownAccount";
                } else if (IncorrectCredentialsException.class.getName().equals(exception)) {
                    msg = "incorrectPassword";
                } else if ("kaptchaValidateFailed".equals(exception)) {
                    System.out.println("kaptchaValidateFailed -- > 验证码错误");
                    msg = "kaptchaValidateFailed -- > 验证码错误";
                } else {
                    msg = "else >> "+exception;
                    System.out.println("else -- >" + exception);
                }
            }
            map.put("msg", msg);
            //认证成功由shiro框架自行处理
            return "login";
        }
      
    
          //访问此连接时会触发MyShiroRealm中的权限分配方法
        @RequestMapping("/permission")
        @RequiresPermissions("student:test")
        public void test(){
            System.out.println("permission  test");
        }
    }

    相关文章

      网友评论

      本文标题:Spring Boot 集成 Shiro权限框架

      本文链接:https://www.haomeiwen.com/subject/phuslftx.html