使用shiro过程中,有时url会遇到JSESSIONID这个小尾巴,去掉小尾巴的解决方法:
1、其实shiro在1.3.2版本已经解决了这个问题,只需配置一下参数即可。
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<property name="globalSessionTimeout" value="1800000"/>
<property name="sessionValidationInterval" value="1200000"/>
<property name="sessionIdUrlRewritingEnabled" value="false" />
<property name="sessionValidationSchedulerEnabled" value="true"/>
<property name="sessionDAO" ref="sessionDAO"/>
<property name="sessionIdCookie" ref="sessionIdCookie"/>
<property name="sessionIdCookieEnabled" value="true"/>
</bean>
2、低于1.3.2版本处理方法:(原理)在我们点击登陆之后会访问DefaultSecurityManager构建Subject。创建Subject之前会做很多事(创建cookie和session等等)其中会访问一下DefaultWebSessionManager的getReferencedSessionId方法。方法里面判断cookie里面是否有sessionid。肯定是没有的啦所以不会向request里面存放ShiroHttpServletRequest的3个静态属性。然后在org.apache.shiro.web.filter.authc.FormAuthenticationFilter登陆成功跳转页面的时候。issueSuccessRedirect方法里面会判断request是否有ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE如果有直接跳转到成功页面。具体判断的代码在ShiroHttpServletRequest里面的isRequestedSessionIdFromURL方法上。如果没有会在跳转成功页面url后面加上JSESSIONID。所以url上就多出了JSESSIONID.然后跳转首页时又会访问DefaultSecurityManager构建Subject。同样会进DefaultWebSessionManager的getReferencedSessionId方法这个时候sessionid有值所以request里面存放了
ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE。这就是为什么我们删掉JSESSIONID他又不加上的原因。因为你后面每次访问。构建subject的时候sessionid有值request的里面也有值他就不会在url上加JSESSIONID了啊。假设我们删除浏览器cookie这个时候没有了sessionid。我们访问当前地址。同样会创建Subject。由于sessionid没有了所以request里面就不会存值了。然后会进入org.apache.shiro.web.filter.authc.UserFilter判断subject是否有认证信息。没有会通过saveRequestAndRedirectToLogin跳转到登陆页面。saveRequestAndRedirectToLogin里面判断request是否有值没值又会在跳转页面的url上加上JSESSIONID。然后进入登陆界面的时候构建subject 创建session request里面存值。好了说完了。看不懂得自己脑补把。
- private Serializable getReferencedSessionId(ServletRequest request, ServletResponse response) {
-
- String id = getSessionIdCookieValue(request, response);
- if (id != null) {
- request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
- ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);
- } else {
-
-
-
- id = getUriPathSegmentParamValue(request, ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
-
- if (id == null) {
-
- String name = getSessionIdName();
- id = request.getParameter(name);
- if (id == null) {
-
- id = request.getParameter(name.toLowerCase());
- }
- }
- if (id != null) {
- request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
- ShiroHttpServletRequest.URL_SESSION_ID_SOURCE);
- }
- }
-
- public boolean isRequestedSessionIdFromURL() {
- if (isHttpSessions()) {
- return super.isRequestedSessionIdFromURL();
- } else {
- String value = (String) getAttribute(REFERENCED_SESSION_ID_SOURCE);
- return value != null && value.equals(URL_SESSION_ID_SOURCE);
- }
- }
我的办法在每次跳转之前就判断sessionid是否有值。因为每次跳转之前subject就已经创建了session。至于如果禁用cookies。同样还是会在url上加上jsessionid。我们只是把判断给至前了。并没有修改原有逻辑。具体代码如下
-
-
-
-
-
-
-
- public class UserFilter extends AccessControlFilter{
-
- private Cookie sessionIdCookie;
-
- public Cookie getSessionIdCookie() {
- return sessionIdCookie;
- }
-
-
- public void setSessionIdCookie(Cookie sessionIdCookie) {
- this.sessionIdCookie = sessionIdCookie;
- }
-
- @Override
- protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
- if (isLoginRequest(request, response)) {
- return true;
- } else {
- Subject subject = getSubject(request, response);
-
- return subject.getPrincipal() != null;
- }
- }
-
- @Override
- protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
- saveRequest(request);
- String sessionid = sessionIdCookie.readValue(WebUtils.toHttp(request), WebUtils.toHttp(response));
-
- if(sessionid != null){
- request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);
- request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sessionid);
- request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
- }
- redirectToLogin(request, response);
- return false;
- }
- }
-
-
-
-
-
-
-
- public class LoginFilter extends FormAuthenticationFilter{
-
- private Cookie sessionIdCookie;
-
- public Cookie getSessionIdCookie() {
- return sessionIdCookie;
- }
-
-
- public void setSessionIdCookie(Cookie sessionIdCookie) {
- this.sessionIdCookie = sessionIdCookie;
- }
-
-
- @Override
- protected void setFailureAttribute(ServletRequest request, AuthenticationException ae) {
- request.setAttribute(getFailureKeyAttribute(), ae);
- }
-
- @Override
- protected void issueSuccessRedirect(ServletRequest request, ServletResponse response) throws Exception {
- String sessionid = sessionIdCookie.readValue(WebUtils.toHttp(request), WebUtils.toHttp(response));
-
- if(sessionid != null){
- request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);
- request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sessionid);
- request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
- }
- super.issueSuccessRedirect(request, response);
- }
- }
另一种解决办法:
- public class RedisWebSessionManager extends DefaultWebSessionManager {
-
-
-
-
-
- @Override
- protected void onStart(Session session, SessionContext context) {
- super.onStart(session, context);
- ServletRequest request = WebUtils.getRequest(context);
- request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);
- }
-
- }