springboot整合shiro

1、先写shiro的配置类
@Configuration
public class ShiroConfig {

    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilterBean(
            @Qualifier("securityManager") SecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 如果不设置默认会自动寻找Web工程根目录下的"/login"页面
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 登录成功后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("index/index.html");

        //拦截器.
        Map filterChainDefinitionMap = new LinkedHashMap();
        // 配置不会被拦截的链接 顺序判断
        filterChainDefinitionMap.put("/", "anon");
        filterChainDefinitionMap.put("/common/**", "anon");
        filterChainDefinitionMap.put("/favicon.ico", "anon");
        filterChainDefinitionMap.put("/error/**", "anon");
        // 配置退出 过滤器,其中的具体的退出代码Shiro已经实现了
        filterChainDefinitionMap.put("/logout", "logout");
        //:这是一个坑呢,一不小心代码就不好使了;
        //
        filterChainDefinitionMap.put("/**", "authc");

        //未授权界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }


    @Bean
    public SecurityManager securityManager(@Qualifier("communityRealm") CommunityRealm realm, @Qualifier("userDao")UserDao userDao) {
        realm.setUserDao(userDao);
//        realm.setCredentialsMatcher();
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm);
        return securityManager;
    }

    @Bean("communityRealm")
    public CommunityRealm communityRealm(){
        CommunityRealm communityRealm = new CommunityRealm();
        return communityRealm;
    }

}
注意,经再三验证,这里有个bug,如果没有配置这句
 filterChainDefinitionMap.put("/", "anon");

那么shiro在用户登录退出之后,之后再登陆就不会自动跳转到设置好的index页面。

由于配置了上面的这个链接,即可以访问 http://主机名:端口/,所以需要做相应的配置,因此在loginController里面需要配置,如下:

@Controller
public class LoginController {

    /**
     * 圈子首页,登录页面
     * @return
     */
    @GetMapping("/")
    public String index() {
        return "login/login";
    }

    /**
     * 认证
     * @return
     */
    @RequestMapping("/login")
    public String login(HttpServletRequest request) throws Exception{
        // shiro在认证过程中出现错误后将异常类路径通过request返回
        String exceptionClassName = (String) request
                .getAttribute("shiroLoginFailure");
        // 登陆有错误,继续跳转登陆页面
        if(exceptionClassName != null){
            if (UnknownAccountException.class.getName().equals(exceptionClassName)) {
                throw new Exception("账号不存在");
            } else if (IncorrectCredentialsException.class.getName().equals(
                    exceptionClassName)) {
                throw new Exception("用户名/密码错误");
            } else if("randomCodeError".equals(exceptionClassName)){
                throw new Exception("验证码错误");
            } else{
//                throw new Exception();//最终在异常处理器生成未知错误
            }

            return "login/login";
        }

        Subject subject = SecurityUtils.getSubject();
        // 没有登陆
        if (subject == null || !subject.isAuthenticated()) {
            return "login/login";
        }

        return "index/index";
    }

}

最后,自定义一个用于验证shiro用户认证 和 授权的realm,这里暂时只实现了realm的认证,代码如下:

public class CommunityRealm extends AuthorizingRealm {

    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    /**
     * 授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    /**
     * 认证
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        if (this.userDao == null) {
            return null;
        }
        String usercode = (String) token.getPrincipal();
        User user = userDao.findUserByUsercode(usercode);
        if (user == null) {
            return null;
        }

        SimpleAuthenticationInfo simpleAuthenticationInfo
                = new SimpleAuthenticationInfo(user,user.getPassword(),"communityRealm");
        return simpleAuthenticationInfo;
    }

}

如果,有爱好java或者springboot项目的,欢迎加入群交流431445096



你可能感兴趣的:(springboot)