前后端分离项目使用Shiro

前后端分离项目使用Shiro

前面文章将的shiro使用都是局限于单体应用,但是在前后端分离中就会有会话存储的问题,所以这篇文章就是为了解决前后端分离项目中使用shiro的会话问题。

我们用到的是redis来存储会话信息。

一:导入shiro整合redis的jar包

<dependency>
     <groupId>org.crazycake</groupId>
     <artifactId>shiro-redis</artifactId>
     <version>2.4.2.1-RELEASE</version>
</dependency>

二:自定义一个SessionManager

import java.io.Serializable;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.util.StringUtils;

public class MySessionManager extends DefaultWebSessionManager {
	
    private static final String AUTHORIZATION = "Authorization";
	
    public MySessionManager() {  
        super();  
    }  
  
    @Override  
    protected Serializable getSessionId(ServletRequest request, ServletResponse response) {  
    	//前端ajax的headers中必须传入Authorization的值
        String id = WebUtils.toHttp(request).getHeader(AUTHORIZATION);  
        //如果请求头中有 Authorization 则其值为sessionId  
        if (!StringUtils.isEmpty(id)) {  
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);  
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);  
            return id;  
        } else {  
            //否则按默认规则从cookie取sessionId  
            return super.getSessionId(request, response);  
        }  
    }  
}

三:ShiroConfig配置文件注入SessionManager

加上下面的代码:

	/**
     * 2.自定义sessionManager,用户的唯一标识,即Token或Authorization的认证
     */
@Bean
public SessionManager sessionManager() {
    //创建一个上面自定的SessionManager
    MySessionManager mySessionManager = new MySessionManager();
    mySessionManager.setSessionDAO(redisSessionDAO());
    return mySessionManager;
}

	/**
     * 配置shiro redisManager 使用的是shiro-redis开源插件
     * @return
     */
public RedisManager redisManager() {
    RedisManager redisManager = new RedisManager();
    //redis链接信息
    redisManager.setHost("127.0.0.1");
    redisManager.setPort(6379);
    redisManager.setExpire(1000*60*60*24);
    redisManager.setTimeout(30000);
    redisManager.setPassword("123456");
    return redisManager;
}

@Bean
public RedisSessionDAO redisSessionDAO() {
    RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
    // 自定义session管理 使用redis
    redisSessionDAO.setRedisManager(redisManager());
    return redisSessionDAO;
}

四:将SessionManager注入安全管理器

在这里插入图片描述

到这里配置就做完了,然后是业务流程

五:修改登陆

subject.login(token);
//将authorization传给前端,用于MySessionManager中请求的验证
return (String)subject.getSession().getId(); 

在用户登陆成功之后,将authorization传入前端,由前端放入headers中,当用户访问其他接口的时候,就会携带上这个键值对:

在这里插入图片描述

这样就能正常访问,如果不携带这个值,则找不到当前用户的登陆凭证信息,则为未登录状态:

在这里插入图片描述

六:退出登陆

用户退出登陆的时候,后端只需要执行下面的代码就行了:

SecurityUtils.getSubject().logout();

七:获取当前登陆信息

	@Autowired  
    private RedisSessionDAO redisSessionDAO;  
	
	public SysUser getUserByHeader(ServletRequest request) throws Exception{
		//前端ajax的headers中必须传入Authorization的值
		String id = WebUtils.toHttp(request).getHeader("Authorization"); 
		Session session = redisSessionDAO.readSession(id);
		Object obj = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
		SimplePrincipalCollection coll = (SimplePrincipalCollection) obj;
		String userStr = JSON.toJSON(coll.getPrimaryPrincipal()).toString();
		SysUser user = JSON.parseObject(userStr, SysUser.class);
        return user;
	}
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值