Springboot整合Shiro

Maven中引入Shiro依赖

 <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.7.0</version>
        </dependency>
        
	<-- shiro整合Thymeleaf模板的依赖-->
		<dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>
        <--导入这个依赖之后在shiro的配置文件中加入下段代码
			/* shiro方言  让thymeleaf支持shiro标签
		     * @return
		     */
		    @Bean
		    public ShiroDialect shiroDialect() {
		        return new ShiroDialect();
		    }
		-->

ShiroConfig配置文件

package com.lwk.shiro.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {

	//shiro拦截器
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //设置安全管理器
        bean.setSecurityManager(defaultWebSecurityManager);
        //添加shiro内置过滤器
        /*
            anon 无需认证就能访问
            authc 必须认证才能访问
            user 必须使用记住我功能才能访问
            perms 拥有对某个资源的权限才能访问
        */
        Map<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/shiro/*", "anon");//例:/shiro路径下的所有资源无需认证就能访问
        filterMap.put("/signUp", "anon");
        filterMap.put("/**", "authc");//拦截所有资源
        bean.setUnauthorizedUrl("/"); //未通过认证跳转到的页面
        bean.setLoginUrl("/"); //设置默认登录页面
        bean.setFilterChainDefinitionMap(filterMap);//注入拦截资源的Map
        return bean;
    }

    /**
     * 配置核心安全事务管理器
     *
     * @param userRealm
     * @return
     */
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联UserRealm
        securityManager.setRealm(userRealm);
        securityManager.setRememberMeManager(rememberMeManager());
        securityManager.setSessionManager(mySessionManager());
        return securityManager;
    }

    /**
     * 配置shiro 的session管理 相当于 HttpServletSession
     *
     *
     * @return
     */
    @Bean
    public DefaultWebSessionManager mySessionManager(){
        DefaultWebSessionManager defaultSessionManager = new DefaultWebSessionManager();
        defaultSessionManager.setSessionValidationSchedulerEnabled(false);
        //将sessionIdUrlRewritingEnabled属性设置成false
        defaultSessionManager.setSessionIdUrlRewritingEnabled(false);
        defaultSessionManager.setGlobalSessionTimeout(1000*60*60*24);
        return defaultSessionManager;
    }
    //创建realm对象,自定义类
    @Bean(name = "userRealm")
    public UserRealm userRealm() {
        return new UserRealm();
    }

    /**
     * cookie管理对象;记住我功能,rememberMe管理器
     *
     * @return
     */
    @Bean
    public CookieRememberMeManager rememberMeManager() {
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(simpleCookie());
        //rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
        cookieRememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
        return cookieRememberMeManager;
    }

    /**
     * FormAuthenticationFilter 过滤器 过滤记住我
     *
     * @return
     */
    @Bean
    public FormAuthenticationFilter formAuthenticationFilter() {
        FormAuthenticationFilter formAuthenticationFilter = new FormAuthenticationFilter();
        //对应前端的checkbox的name = rememberMe
        formAuthenticationFilter.setRememberMeParam("rememberMe");
        return formAuthenticationFilter;
    }

    /**
     * cookie对象;会话Cookie模板 ,默认为: JSESSIONID 问题: 与SERVLET容器名冲突,重新定义为sid或rememberMe,自定义
     *
     * @return
     */
    @Bean
    public SimpleCookie simpleCookie() {
        //这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        //setcookie的httponly属性如果设为true的话,会增加对xss防护的安全系数。它有以下特点:
        //setcookie()的第七个参数
        //设为true后,只能通过http访问,javascript无法访问
        //防止xss读取cookie
        simpleCookie.setHttpOnly(true);
        simpleCookie.setPath("/");
        simpleCookie.setMaxAge(60 * 60 * 24 * 15);
        return simpleCookie;
    }

}

创建自己的UserRealm类

package com.lwk.shiro.config;

import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
public class UserRealm extends AuthorizingRealm {

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        //拿到当前登录的对象

        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //1.把AuthenticationToken转换为UsernamePasswordToken
        //usernamePasswordToken 中保存着前端用户输入的用户名或者密码和是否记住我(例如 admin 123  false)
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
        //2.从usernamePasswordToken中获取username
        String username=usernamePasswordToken.getUsername();
        //3.调用方法从数据库中获取用户信息
        String usernmae= xxx;//我这里查的用户名
        //4.用户不存在的时候抛出UnknownException
        if (uasername==null){//这里可以自己抛出shiro中的异常,看自己需求
            throw new UnknownAccountException("用户不存在");
        }
        //5.根据用户情况 来构建AuthenticationInfo对象并返回
        //5.1.principal:认证的实体信息,可以是username,也可以是用户对应数据库的实体配
        Object principal=username;
        //5.2.credentials:密码
        Object credentials=xxx;//数据库中获取用户的密码
        //5.3.realmName: 当前realm对象的name,调用父类的getName即可
        SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(principal,credentials,getName() );


        return info;
    }
}

UserController中使用shiro的登录

package com.lwk.shiro.controller;

import com.lwk.shiro.pojo.User;
import com.lwk.shiro.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Controller
@RequestMapping("/shiro")
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private HttpServletResponse response;

    @ResponseBody
    @RequestMapping(value = "login", method = RequestMethod.POST)
    public String login(User user) {
        if (user == null) {
            return "账号密码不能为空";
        }
        UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword(), false);
        Subject subject = SecurityUtils.getSubject();
        //登录验证这里可以捕获到shiro的异常并反馈信息
        //这些异常可以根据自己的需要来处理
        try {
            subject.login(token);
        } catch (UnknownAccountException uae) {//账号不存在
            return uae.getMessage();
        } catch (IncorrectCredentialsException ice) {//登录信息验证错误
            return "账号密码错误";
        }
        
        try {
            response.sendRedirect("/index");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }
	//这里可以使用shiro的登出(注销登陆)
    @RequestMapping("logout")
    public String logout() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "redirect:/";
    }
}

使用shiro登陆之后可以通过下面这句代码拿到 登录的 user对象
User user = (User) subject.getPrincipal();

shiro中的异常可以看看shiro中的异常的继承关系或者下面这篇博客

shiro异常类

上一篇:vtkOrientationMarkerWidget在Qt窗口中不显示


下一篇:shiro安全框架的使用