Springboot整合Shiro

nullcy 2020-04-25

Springboot整合Shiro

1、导入依赖

<!--https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring-boot-web-starter-->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring-boot-web-starter</artifactId>
        <version>1.5.2</version>
    </dependency>

2、配置ShiroConfig

  • 目录如下

    com

    config

    ShiroConfig.java

    UserRealm.java

    controller

    RouterController.java

    SpringbootShrioApplication

  • shiro有三个核心(配置时都必须装配成Bean):

    • Subject(用户)
    • SecurityManager(管理用户)
  • Realm(连接数据)

  • 开始配置ShiroConfig,从底层开始配置(从下往上),Realm需要额外写一个类UserRealm,这个类便是shiro的核心

    @Configuration
    public class ShiroConfig{
        
        //shriofilterbean
        //这个方法名必须为shiroFilterFactoryBean,否则报错
        @Bean
        public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
            System.out.println("");
            ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
            //关联securityManager
            bean.setSecurityManager(securityManager);
    
            //给请求设置权限
            //authc:需要认证才可访问
            //anon:无需认证也能访问
            Map<String,String> filter = new LinkedHashMap<>();
            filter.put("/user/*","authc");
            filter.put("/","anon");
            bean.setFilterChainDefinitionMap(filter);
    
            //当没有权限,跳转到此登陆界面
            bean.setLoginUrl("/login");
    
            return bean;
        }
    
        //securityManager
        @Bean
        public DefaultWebSecurityManager securityManager(@Qualifier("realm") UserRealm realm){
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            //关联realm
            securityManager.setRealm(realm);
            return securityManager;
        }
    
        //realm
        @Bean
        public UserRealm realm(){
            return new UserRealm();
      }

    UserRealm只需继承AuthorizingRealm类即可,要实现如下两个方法,本类为shiro核心:

    //自定义的realm
    public class UserRealm extends AuthorizingRealm {
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            System.out.println("授权");
            return null;
        }
    
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            System.out.println("认证");
            return null;
        }
    }

3、实现用户登陆认证

  • 流程:

    • 将用户提交的表单信息封装成令牌token
    • 用token登陆,此时调用UserRealm类中的doGetAuthenticationInfo()方法来进行认证
    • 若用户名或密码错误,doGetAuthenticationInfo()会抛出异常,反之,若无异常抛出,则登陆成功
  • controller接受请求代码(用户提交表单时用controller接收):

    @RequestMapping("/login")
    public String login(String usr, String pwd, Model model){
    
        //获取当前用户
        Subject subject = SecurityUtils.getSubject();
    
        //封装用户的登陆数据,生成令牌
        UsernamePasswordToken token = new UsernamePasswordToken(usr,pwd);
    
        //用令牌登陆,如果没有异常则登陆成功
        try{
            subject.login(token);
            //无异常则登陆成功
            return "index";
        }catch(UnknownAccountException e){
            model.addAttribute("msg","用户名错误");
            return "login";
        }catch(IncorrectCredentialsException e){
            model.addAttribute("msg","密码错误");
            return "login";
        }
    }
  • getAuthenticationInfo()代码:

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("认证");
        //用户名,密码,应该从数据库取,此处仅测试
        String usr="wagn";
        String pwd="123";
    
        //先取令牌
        UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
    
        //验证用户名
        if(!usr.equals(token.getUsername())){
            return null;
        }
    
        //验证密码,Shiro自动验证,只需要把数据库的密码传过去就好了
        return new SimpleAuthenticationInfo("",pwd,"");
    }

相关推荐