Springboot Shiro实现用户验证

添加依赖

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-jdbcartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-thymeleafartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.mybatis.spring.bootgroupId>
            <artifactId>mybatis-spring-boot-starterartifactId>
            <version>2.1.1version>
        dependency>

        
        <dependency>
            <groupId>org.apache.shirogroupId>
            <artifactId>shiro-springartifactId>
            <version>1.4.0version>
        dependency>

        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>5.1.48version>
        dependency>

shiro配置类

@Configuration
public class ShiroConfig {
     
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") SecurityManager securityManager) {
     
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 设置securityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 登录的url
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 登录成功后跳转的url
        shiroFilterFactoryBean.setSuccessUrl("/index");
        // 未授权url
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");

        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();

        // 定义filterChain,静态资源不拦截
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/fonts/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        // druid数据源监控页面不拦截
        filterChainDefinitionMap.put("/druid/**", "anon");
        // 配置退出过滤器,其中具体的退出代码Shiro已经替我们实现了
        filterChainDefinitionMap.put("/logout", "logout");
        filterChainDefinitionMap.put("/", "anon");
        // 除上以外所有url都必须认证通过才可以访问,未通过认证自动访问LoginUrl
        filterChainDefinitionMap.put("/**", "authc");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    @Bean
    public SecurityManager securityManager(){
     
        // 配置SecurityManager,并注入shiroRealm
        DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
        securityManager.setRealm(shiroRealm());
        return securityManager;
    }

    @Bean
    public ShiroRealm shiroRealm(){
     
        // 配置Realm,需自己实现
        ShiroRealm shiroRealm = new ShiroRealm();
        return shiroRealm;
    }
}

注意filterChain基于短路机制,即最先匹配原则

/user/**=anon
/user/aa=authc 永远不会执行

Shiro内置的过滤器

自定义Realm

自定义realm需要继承AuthorizingRealm。实现doGetAuthorizationInfo(用于授权)与doGetAuthenticationInfo(用于认证)方法。

public class ShiroRealm extends AuthorizingRealm {
     

    @Autowired
    private UserMapper userMapper;

    /**
     * 获取用户角色和权限
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
     
        return null;
    }

    /**
     * 登录认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
     

        // 获取用户输入的用户名和密码
        String userName = (String) token.getPrincipal();
        String password = new String((char[]) token.getCredentials());

        System.out.println("用户" + userName + "认证-----ShiroRealm.doGetAuthenticationInfo");

        // 通过用户名到数据库查询用户信息
        User user = userMapper.findByUserName(userName);

        if (user == null) {
     
            throw new UnknownAccountException("用户名或密码错误!");
        }
        if (!password.equals(user.getPassword())) {
     
            throw new IncorrectCredentialsException("用户名或密码错误!");
        }
        if (user.getStatus().equals("0")) {
     
            throw new LockedAccountException("账号已被锁定,请联系管理员!");
        }
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
        return info;
    }

controller

登录验证功能实现

@PostMapping("/login")
    @ResponseBody
    public ResponseBo login(String username, String password) {
     
    	// 密码MD5加密
        password = MD5Utils.encrypt(username, password);
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        // 获取Subject对象
        Subject subject = SecurityUtils.getSubject();
        try {
     
            subject.login(token);
            return ResponseBo.ok();
        } catch (UnknownAccountException e) {
     
            return ResponseBo.error(e.getMessage());
        } catch (IncorrectCredentialsException e) {
     
            return ResponseBo.error(e.getMessage());
        } catch (LockedAccountException e) {
     
            return ResponseBo.error(e.getMessage());
        } catch (AuthenticationException e) {
     
            return ResponseBo.error("认证失败!");
        }
    }

你可能感兴趣的:(Spring)