美文网首页
springboot笔记-整合shiro

springboot笔记-整合shiro

作者: DN花花 | 来源:发表于2019-03-18 22:26 被阅读0次

    1.shiro 核心api

    Subject : 用户主体,把操作交给SecurityManger
    SecurityManger : 安全管理器 ,关联Realm
    Realm : Shiro 连接数据的桥梁

    2.引入依赖包

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

    3.创建UserRealm类

    import com.dntest.springbootshiro.user.model.Module;
    import com.dntest.springbootshiro.user.model.Role;
    import com.dntest.springbootshiro.user.model.User;
    import com.dntest.springbootshiro.user.service.UserService;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.*;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.apache.shiro.subject.Subject;
    import org.springframework.beans.factory.annotation.Autowired;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Set;
    
    /**
     * @version V1.0
     * @author: MR.DN
     * @ClassName: UserRealm
     * @Date: 2019/3/18 15:49
     * @Description: TODO
     */
    public class UserRealm extends AuthorizingRealm {
        @Autowired
    UserService userService;
        /**
         * 执行授权逻辑
         * @param principalCollection
         * @return
         */
       @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            System.out.println("执行授权逻辑");
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            Subject subject = SecurityUtils.getSubject();
            User user = (User)subject.getPrincipal();
            Set<Role> roles = user.getRoles();
            for(Role role : roles){
                //授权账户角色
                info.addRole(role.getRname());
                Set<Module> modules = role.getModules();
                for(Module module : modules){
                    //授权账户权限
                    info.addStringPermission(module.getMname());
                }
            }
            return info;
        }
    
        /**
         * 执行认证逻辑
         * @param authenticationToken
         * @return
         * @throws AuthenticationException
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            System.out.println("执行认证逻辑");
            UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
            String username = token.getUsername();
            User user = userService.findByUsername(username);
            if(user==null){
                return null;
            }
            return  new SimpleAuthenticationInfo(user,user.getPassword(),this.getClass().getName());
        }
    }
    
    

    4.编写shiro配置类ShiroConfig

    @Configuration
    public class ShiroConfig {
      /**
         *  1.注入shiro过滤器工厂  ShiroFilterFactoryBean
         *  2.注入自定义realm        userRealm
         *  3.注入安全管理器         DefaultWebSecurityManager
         *  4.密码加密比较器         CredentialsMatcher
         *  5.生命周期              LifecycleBeanPostProcessor
         */
     
    }
    

    加 注解@ Configuration

    • 1.常用过滤器
     shiro 内置过滤器 实现相关拦截
          常用拦截器
          anon 无需认证
          authc 必须认证
          user  如果使用rememberMe 的功能可以直接使用
          perms 该资源必须得到资源权限才可以访问
          role 该资源必须得到角色权限才可访问
    
    • 2.创建DefaultWebSecurityManger
     @Bean(name = "securityManager")
     public DefaultWebSecurityManager getDefaultWebSecurityManger(@Qualifier("userRealm")UserRealm userRealm){
            DefaultWebSecurityManager securityManger = new DefaultWebSecurityManager();
            //关联Realm
            securityManger.setRealm(userRealm);
            return securityManger;
        }
    
    • 3.创建Realm
    @Bean(name="userRealm")
        public UserRealm getRealm(){
            return new UserRealm();
        }
    
    • 4.创建ShiroFilterFactoryBean

    注意顺序,anon 在最前面,authc在最后

      @Bean
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
            ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
            //设置安全管理器
            bean.setSecurityManager(securityManager);
            bean.setLoginUrl("/tologin");
            bean.setUnauthorizedUrl("/unAuth");
            LinkedHashMap<String, String> filterChainDefinitionMap=new LinkedHashMap<>();
            //表示可以匿名访问
            filterChainDefinitionMap.put("/tologin", "anon");
            filterChainDefinitionMap.put("/login", "anon");
            //表示必须认证才能访问访问
            filterChainDefinitionMap.put("/**", "authc");
            bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
            return bean;
        }
    
    
    • 5.配置自定义的密码比较器
    //配置自定义的密码比较器
        @Bean(name="credentialsMatcher")
        public CredentialsMatcher credentialsMatcher() {
            return new CredentialsMatcher();
        }
    //新建一个类
    public class CredentialsMatcher extends SimpleCredentialsMatcher {
    
        @Override
        public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
            UsernamePasswordToken upToken = (UsernamePasswordToken) token;
            String inPassword = new String(upToken.getPassword());
            String password = (String) info.getCredentials();
            return this.equals(inPassword,password);
        }
    }
    
    • 6.配置生命周期
     @Bean
        public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
            return new LifecycleBeanPostProcessor();
        }
        @Bean
        public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
            DefaultAdvisorAutoProxyCreator creator=new DefaultAdvisorAutoProxyCreator();
            creator.setProxyTargetClass(true);
            return creator;
        }
        @Bean
        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager manager) {
            AuthorizationAttributeSourceAdvisor advisor=new AuthorizationAttributeSourceAdvisor();
            advisor.setSecurityManager(manager);
            return advisor;
        }
    

    5.整合mybatis

    • 引入依赖
     <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.0.0</version>
     </dependency>
     <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.0.11</version>
     </dependency>
     <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
     </dependency>
    
    • 配置文件
    spring.datasource.url=jdbc:mysql://127.0.0.1:3306/img?characterEncoding=UTF-8
    spring.datasource.username=test
    spring.datasource.password=123456
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver  
    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
    
    • 创建表
    1. 建表语句
    CREATE TABLE `user` (
     `uid` int(11) NOT NULL AUTO_INCREMENT,
     `username` varchar(255) DEFAULT NULL,
     `password` varchar(255) DEFAULT NULL,
     PRIMARY KEY (`uid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
    
    CREATE TABLE `role` (
     `rid` int(11) NOT NULL AUTO_INCREMENT,
     `rname` varchar(255) DEFAULT NULL,
     PRIMARY KEY (`rid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
    
    CREATE TABLE `module` (
     `mid` int(11) NOT NULL AUTO_INCREMENT,
     `mname` varchar(255) DEFAULT NULL,
     PRIMARY KEY (`mid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
    
    CREATE TABLE `user_role` (
     `uid` int(11) DEFAULT NULL,
     `rid` int(11) DEFAULT NULL,
     KEY `u_fk` (`uid`),
     KEY `r_fk` (`rid`),
     CONSTRAINT `r_fk` FOREIGN KEY (`rid`) REFERENCES `role` (`rid`),
     CONSTRAINT `u_fk` FOREIGN KEY (`uid`) REFERENCES `user` (`uid`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8
    
    CREATE TABLE `module_role` (
     `rid` int(11) DEFAULT NULL,
     `mid` int(11) DEFAULT NULL,
     KEY `rid` (`rid`),
     KEY `mid` (`mid`),
     CONSTRAINT `mid` FOREIGN KEY (`mid`) REFERENCES `module` (`mid`),
     CONSTRAINT `rid` FOREIGN KEY (`rid`) REFERENCES `role` (`rid`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8
    

    2.对应model

    public class User {
        private Integer uid;
    
        private String username;
    
        private String password;
    
        private Set<Role> roles = new HashSet<>();
    .....
    }
    
    public class Role {
        private Integer rid;
    
        private String rname;
    
        private Set<Role> roles = new HashSet<>();
    
        private Set<Module> modules = new HashSet<>();
    ......
    }
    
    public class Module {
        private Integer mid;
    
        private String mname;
    
        private Set<Module> modules = new HashSet<>();
    ......
    }
    
    • 编写xml
      1.结果集,用户,角色,权限的多对多
    <resultMap id="BaseResultMap" type="com.dntest.springbootshiro.user.model.User" >
        <id column="uid" property="uid" jdbcType="INTEGER" />
        <result column="username" property="username" jdbcType="VARCHAR" />
        <result column="password" property="password" jdbcType="VARCHAR" />
        <collection property="roles" ofType="com.dntest.springbootshiro.user.model.Role">
          <id column="rid" property="rid" jdbcType="INTEGER" />
          <result column="rname" property="rname" jdbcType="VARCHAR" />
          <collection property="modules" ofType="com.dntest.springbootshiro.user.model.Module">
            <id column="mid" property="mid" jdbcType="INTEGER" />
            <result column="mname" property="mname" jdbcType="VARCHAR" />
          </collection>
        </collection>
      </resultMap>
    

    2.sql语句关联,多表查询,把用户对应的角色和权限全部查出来

     <select id="findByUsername" resultMap="BaseResultMap" parameterType="java.lang.String" >
        SELECT u.*,r.*,m.* FROM user u
              left join user_role ur on ur.uid = u.uid
              left join role r on r.rid = ur.rid
              left join module_role mr on mr.rid = r.rid
              left join module m on mr.mid = m.mid
        WHERE username = #{username}
      </select>
    

    5.创建loginController类

    @Controller
    public class LoginController {
        @GetMapping("tologin")
        public String tologin(Model model){
            model.addAttribute("wolcome","欢迎登陆");
            return "login";
        }
        @RequestMapping("login")
        public String login(String username,String password,Model model){
            UsernamePasswordToken upToken = new UsernamePasswordToken(username,password);
            Subject subject = SecurityUtils.getSubject();
            try{
                subject.login(upToken);
            }catch (UnknownAccountException e){
                model.addAttribute("msg","用户名不存在");
                return "login";
            }catch (IncorrectCredentialsException e){
                model.addAttribute("msg","密码错误");
                return "login";
            }
            model.addAttribute("username",username);
            return "index";
        }
    
        @RequestMapping("/logOut")
        public String logOut(HttpSession session) {
            Subject subject = SecurityUtils.getSubject();
            subject.logout();
            return "shiro/login";
        }
    }
    

    相关文章

      网友评论

          本文标题:springboot笔记-整合shiro

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