shiro获取请求头中的sessionId
前⾔:
在前后端项⽬中, 前端有可能会要求, 后台返回⼀个 sessionId 给他, 然后他在请求后台接⼝时, 把这个sessionId 带给后台, 后台拿到这个sessionId , 就能识别, 是那个⽤户.
在shiro中, 会返回⼀个 JSESSIONID , 其实就是sessionId .
如果不想把sessionId 放在参数中, 或者贴在链接后⾯, 暴露给⽤户, 那么我们还能选择把 sessionId 放在请求头中, 这样⽐较隐秘⼀些. 不会那么明显.⼀. DefaultWebSessionManager
在配置shiro的时候, 我们经常会配置 org.apache.shiro.DefaultWebSessionManager , 那么我们先来看看这个类中的相关⽅法吧.
1. onStart ⽅法
在这个⽅法中, 我们其实可以很明显的看到有⼀个storeSessionId ⽅法, 在这个⽅法中, 会将 sessionId 存⼊到cookie中.
如果我们可以继承这个类, 然后重写onStart⽅法, 那么是否可以实现, 将sessionId放到响应头中去, 前端可以从响应头中获取到sessionId.
那既然有处理sesisonId的⽅法, 那么是否有get sessionId的⽅法呢? 如果有这个⽅法, 我们重写它, 改为从请求头中读取sessionid, 不就可以了么.
那来⼀下看看:
确实有的. ⾥⾯的具体实现, 就不看了, 不是这篇的主题.
⼆. ⾃定义 DefaultWebSessionManager 类
import org.apachemons.lang.StringUtils;
import org.apache.shiro.session.ExpiredSessionException;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.Session;
import org.apache.DefaultSessionManager;
import org.apache.DelegatingSession;
import org.apache.SessionContext;
import org.apache.SessionKey;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.WebSessionKey;
import org.apache.shiro.WebSessionManager;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
public class DefaultHeaderSessionManager extends DefaultSessionManager implements WebSessionManager {
private static final Logger log = Logger(DefaultHeaderSessionManager.class);
private final String X_AUTH_TOKEN = "x-auth-token";
@Override
protected void onStart(Session session, SessionContext context) {
//Start(session, context);
if (!WebUtils.isHttp(context)) {
log.debug("SessionContext argument is not HTTP compatible or does not have an HTTP request/response pair. No session ID cookie will be set.");
} else {
HttpServletRequest request = HttpRequest(context);
HttpServletResponse response = HttpResponse(context);
Serializable sessionId = Id();
this.storeSessionId(sessionId, request, response);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
}
}
//获取sessionid
@Override
public Serializable getSessionId(SessionKey key) {
Serializable id = SessionId(key);
if (id == null && WebUtils.isWeb(key)) {
ServletRequest request = Request(key);
ServletResponse response = Response(key);
id = getSessionId(request, response);
}
return id;
}
protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
ReferencedSessionId(request, response);
}
// 请求头中获取 sessionId 并把sessionId 放⼊ response 中
private String getSessionIdHeaderValue(ServletRequest request, ServletResponse response) {
if (!(request instanceof HttpServletRequest)) {
log.debug("Current request is not an HttpServletRequest - cannot get session ID cookie. Returning null.");
return null;
}
else {
HttpServletRequest httpRequest = (HttpServletRequest) request;
// 在request 中读取 x-auth-token 信息作为 sessionId
String sessionId = Header(this.X_AUTH_TOKEN);
// 每次读取之后都把当前的 sessionId 放⼊ response 中
HttpServletResponse httpResponse = (HttpServletResponse) response;
if (StringUtils.isNotEmpty(sessionId)) {
httpResponse.setHeader(this.X_AUTH_TOKEN, sessionId);
log.info("Current session ID is {}", sessionId);
}
return sessionId;
}
}
//获取sessionid
private Serializable getReferencedSessionId(ServletRequest request, ServletResponse response) {
String id = SessionIdHeaderValue(request, response);
//DefaultWebSessionManager 中代码直接copy过来
if (id != null) {
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, "header");
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE); }
//不会把sessionid放在URL后
request.setAttribute(ShiroHttpServletRequest.SESSION_ID_URL_REWRITING_ENABLED, Boolean.FALSE);
return id;
}
// 移除sessionid 并设置为 deleteMe 标识
private void removeSessionIdHeader(HttpServletRequest request, HttpServletResponse response) {
response.setHeader(this.X_AUTH_TOKEN, "deleteMe");
}
/**
* 把sessionId 放⼊ response header 中
* onStart时调⽤
* 没有sessionid时会产⽣sessionid 并放⼊ response header中
*/
private void storeSessionId(Serializable currentId, HttpServletRequest ignored, HttpServletResponse response) { if (currentId == null) {
String msg = "sessionId cannot be null when persisting for subsequent requests.";
throw new IllegalArgumentException(msg);
} else {
String idString = String();
response.setHeader(this.X_AUTH_TOKEN, idString);
log.info("Set session ID header for session with id {}", idString);
}
}
// 创建session
@Override
protected Session createExposedSession(Session session, SessionContext context) {
if (!WebUtils.isWeb(context)) {
ateExposedSession(session, context);
} else {
ServletRequest request = Request(context);
ServletResponse response = Response(context);
SessionKey key = new Id(), request, response);
return new DelegatingSession(this, key);
}
session如何设置和读取}
@Override
protected Session createExposedSession(Session session, SessionKey key) {
if (!WebUtils.isWeb(key)) {
ateExposedSession(session, key);
} else {
ServletRequest request = Request(key);
ServletResponse response = Response(key);
SessionKey sessionKey = new Id(), request, response);
return new DelegatingSession(this, sessionKey);
}
}
@Override
protected void onExpiration(Session s, ExpiredSessionException ese, SessionKey key) {
}
@Override
protected void onInvalidation(Session session, InvalidSessionException ise, SessionKey key) {
}
private void onInvalidation(SessionKey key) {
ServletRequest request = Request(key);
if (request != null) {
}
if (WebUtils.isHttp(key)) {
log.debug("Referenced session was invalid. Removing session ID header.");
} else {
log.debug("SessionKey argument is not HTTP compatible or does not have an HTTP request/response pair. Session ID cookie will not be removed due to invalidated session."); }
}
@Override
protected void onStop(Session session, SessionKey key) {
if (WebUtils.isHttp(key)) {
HttpServletRequest request = HttpRequest(key);
HttpServletResponse response = HttpResponse(key);
log.debug("Session has been stopped (subject logout or explicit stop). Removing session ID cookie.");
} else {
log.debug("SessionKey argument is not HTTP compatible or does not have an HTTP request/response pair. Session ID cookie will not be removed due to stopped session."); }
}
@Override
public boolean isServletContainerSessions() {
return false;
}
}
三. 配置
<bean id="sessionManager" class="kt.web.shiro.headtoken.DefaultHeaderSessionManager">
<property name="sessionDAO" ref="sessionDAO"/>
<property name="globalSessionTimeout" value="3600000"/>
<property name="sessionValidationInterval" value="3600000"/>
</bean>
<bean id="sessionDAO" class="org.apache.is.EnterpriseCacheSessionDAO"/>
四. 演⽰⽅法
1. 通过浏览器访问登录接⼝, 拿到sessionId, 也就是这⾥的 x-auth-token
2. 打开postman, 将x-auth-token放⼊到请求头中, 在访问接⼝
确实可以识别⽤户, 拿到数据.
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论