關於shiro使用時候,cookie被禁用的處理
在shiro使用過程中,保持客戶端的狀態是通過兩種方式關聯。一種方式是通過cookie返回,一種是通過重定向回寫url。但是重定向解決不了ajax請求。 如果客戶端禁用了cookie,會導致shiro無法獲得seesion儲存的認證,授權資訊。導致shiro無法使用。
解決思路:在客戶端與服務端進行互動之前,普通請求通過重定向會寫url帶上會話資訊。ajax請求通過寫訊息頭形式,返回特定錯誤讓客戶端獲取相應頭得到seesionId。如果請求後臺沒有用到seesion,可以不用先獲取會話,否則所有的請求都必須先獲得會話。
客戶端獲取到訊息頭後,儲存會話id,每次請求在通過header帶上會話資訊(一定要帶上,特別是重定向的請求,必須從url獲取到會話id)。
也可以不需要先獲取認證資訊,如果使用cookie形式的方式,是不需要先獲的會話。服務端使用了會話,自動寫cookie到客戶端。但是禁用了cookie,服務端產生了會話,相應得到了正確處理,然後在響應頭裡寫訊息頭,客戶端每次請求都從訊息頭裡獲取會話id,當然這樣實現也是可以的。
程式碼如下,相容cookie模式。
public class OssWebSessionManager extends DefaultWebSessionManager implements WebSessionManager { private static final Logger log = LoggerFactory.getLogger(OssWebSessionManager.class); private boolean sessionIdHeaderEnabled; public static final String HEADER_SESSION_NAME = "X-AUTH-SESSION"; public static final String HEADER_SESSION_ID_SOURCE = "header"; public OssWebSessionManager() { super(); //重定向無法手動帶上header super.setSessionIdUrlRewritingEnabled(true); sessionIdHeaderEnabled=true; } @Override protected Session createExposedSession(Session session,SessionContext context) { return super.createExposedSession(session, context); } @Override protected Session createExposedSession(Session session, SessionKey key) { return super.createExposedSession(session, key); } @Override protected void onStart(Session session, SessionContext context) { super.onStart(session, context); HttpServletRequest request = WebUtils.getHttpRequest(context); HttpServletResponse response = WebUtils.getHttpResponse(context); //用header儲存會話sessionId if (sessionIdHeaderEnabled) { Serializable sessionId = session.getId(); storeSessionId(sessionId, request, response); } } @Override public Serializable getSessionId(SessionKey key) { Serializable id = super.getSessionId(key); if(null != id){ return id; } if (WebUtils.isWeb(key)) { ServletRequest request = WebUtils.getRequest(key); ServletResponse response = WebUtils.getResponse(key); id = getHeaderSessionId(request, response); } return id; } protected Serializable getHeaderSessionId(ServletRequest request, ServletResponse response) { String id=getHeaderSessionId((HttpServletRequest)request); if (id != null) { request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,OssWebSessionManager.HEADER_SESSION_ID_SOURCE); } if (id != null) { request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id); request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE); } request.setAttribute(ShiroHttpServletRequest.SESSION_ID_URL_REWRITING_ENABLED, isSessionIdUrlRewritingEnabled()); return id; } @Override protected void onExpiration(Session s, ExpiredSessionException ese, SessionKey key) { super.onInvalidation(s, ese, key); onInvalidation(key); } @Override protected void onInvalidation(Session session, InvalidSessionException ise, SessionKey key) { super.onInvalidation(session, ise, key); onInvalidation(key); } @Override protected void onStop(Session session, SessionKey key) { super.onStop(session, key); onInvalidation(key); } @Override public boolean isServletContainerSessions() { return false; } private void storeSessionId(Serializable currentId, HttpServletRequest request, HttpServletResponse response) { if (currentId == null) { String msg = "sessionId cannot be null when persisting for subsequent requests."; throw new IllegalArgumentException(msg); } response.setHeader(OssWebSessionManager.HEADER_SESSION_NAME,currentId.toString()); log.trace("Set session ID header for session with id {}", currentId.toString()); } /** * 獲取請求的token */ private String getHeaderSessionId(HttpServletRequest httpRequest){ String sessionId=null; //從header中獲取session sessionId = httpRequest.getHeader(OssWebSessionManager.HEADER_SESSION_NAME); //如果header中不存在token,則從引數中獲取token if(!StringUtils.hasText(sessionId)){ sessionId = httpRequest.getParameter(OssWebSessionManager.HEADER_SESSION_NAME); } return sessionId; } private void onInvalidation(SessionKey key) { if (WebUtils.isWeb(key)) { ServletResponse response = WebUtils.getResponse(key); if(null != response){ ((HttpServletResponse)response).addHeader(OssWebSessionManager.HEADER_SESSION_NAME, ""); } } } public boolean isSessionIdHeaderEnabled() { return sessionIdHeaderEnabled; } public void setSessionIdHeaderEnabled(boolean sessionIdHeaderEnabled) { this.sessionIdHeaderEnabled = sessionIdHeaderEnabled; } }
需要認證的請求
public class OssAuthenticationFilter extends AuthenticationFilter {
private static final Logger log = LoggerFactory.getLogger(OssAuthenticationFilter.class);
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
Subject subject=SecurityUtils.getSubject();
if(isRelogin( request, response, subject)){
return false;
}
return subject.isAuthenticated();
}
protected boolean isRelogin(ServletRequest request, ServletResponse response,Subject subject) throws IOException{
Session session=subject.getSession(false);
if(null == session){
if(isAjax(request)){
//無法手動帶上sessionId,從訊息頭獲取sessionId
session=subject.getSession();
response.getWriter().write(JSON.toJSONString(ResultBuilder.genExpResult(new AppBizException(AppExcCodesEnum.SESSION_TIMEOUT))));
}else{
request.setAttribute(ShiroHttpServletRequest.SESSION_ID_URL_REWRITING_ENABLED, true);
this.saveRequestAndRedirectToLogin(request, response);
}
return true;
}
return false;
}
protected boolean isAjax(ServletRequest request){
String header = ((HttpServletRequest) request).getHeader("X-Requested-With");
if("XMLHttpRequest".equalsIgnoreCase(header)){
return Boolean.TRUE;
}
return Boolean.FALSE;
}
}
不需要認證,只需要有會話的請求public class OssNoAuthenticationFilter extends OssAuthenticationFilter {
private static final Logger log = LoggerFactory.getLogger(OssNoAuthenticationFilter.class);
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
Subject subject=SecurityUtils.getSubject();
if(isRelogin( request, response, subject)){
return false;
}
return true;
}
}
shiro過濾器配置
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- Shiro的核心安全介面,這個屬性是必須的 -->
<property name="securityManager" ref="securityManager"/>
<!-- 要求登入時的連結(可根據專案的URL進行替換),非必須的屬性,預設會自動尋找Web工程根目錄apos.htmlhtml"頁面 -->
<property name="loginUrl" value="${shiro.loginUrl}"/>
<!-- 登入成功後要跳轉的連線 -->
<property name="successUrl" value="/sys/manager/index"/>
<!-- 使用者訪問未對其授權的資源時,所顯示的連線 -->
<!-- 若想更明顯的測試此屬性可以修改它的值,如unauthor.jsp-->
<property name="unauthorizedUrl" value="/sys/manager/login"/>
<property name="filters">
<map>
<entry key="authc">
<bean class="tc.oss.web.shiro.OssAuthenticationFilter" />
</entry>
<entry key="noAuthc">
<bean class="tc.oss.web.shiro.OssNoAuthenticationFilter" />
</entry>
<entry key="validCode">
<bean class="tc.oss.web.shiro.ValidCodeAuthenticationFilter">
<property name="validCodeUrl" value="/sys/manager/validCode" />
</bean>
</entry>
<!-- <entry key="ssl">
<ref bean="sslFilter" />
</entry> -->
</map>
</property>
<property name="filterChainDefinitions">
<value>
/statics/**=anon
/js/**=anon
/page/**=anon
/sys/manager/login=noAuthc
/sys/manager/captcha=noAuthc
/favicon.ico=anon
/sys/manager/validCode=authc
/sys/manager/commitCode=authc
/**=authc
</value>
</property>
</bean>
這樣客戶端禁用cookie也能用了,請求必須帶上header。從url或者響應中獲取
url回撥的
function refreshCode(){ var sid=window.location.href.split(";")[1].split("=")[1]; $.ajax({ type: "GET", url: "${contextPath}/sys/manager/captcha?t=" + $.now(), beforeSend: function (XMLHttpRequest) { var sessionid = "X-AUTH-SESSION"; XMLHttpRequest.setRequestHeader(sessionid, sid); }, success: function(r){ $("#captchaImg").attr("src",r); } }); }
ajax非同步請求的沒測試了,應該是沒問題的了
相關推薦
關於shiro使用時候,cookie被禁用的處理
在shiro使用過程中,保持客戶端的狀態是通過兩種方式關聯。一種方式是通過cookie返回,一種是通過重定向回寫url。但是重定向解決不了ajax請求。 如果客戶端禁用了cookie,會導致shiro無法獲得seesion儲存的認證,授權資訊。導致shir
Cookie與Session 的區別,cookie被禁用,session是否還可以被使用?
什麼是Cookie,什麼是cookie會話機制?cookie與session的區別(這裡寫自定義目錄標題) cookie的內容主要包括:名字,值,過期時間,路徑和域。路徑與域一起構成cookie的作用範圍。 若不設定過期時間,則表示這個cookie的生命期為瀏覽器會話期間,關閉瀏
控制元件system.windows.forms.Label在設計器中引發了一個未經處理的異常,已被禁用
問題出現在MDI窗體中,用PictureBox作為MDI窗體背景圖片(更改MDI窗體背景屬性執行效果不是很理想)問題出現了,畫一個控制元件它會報錯,提示 給控制元件設定一下父容器。 程式碼:labe
使用URL重寫解決 Cookie被禁用,導致的使用者Session遺失
大家都知道使用者和web應用互動,通過Session的方式。 那麼客戶端是如何在伺服器上一下子找到屬於自己的那個Session呢? 一般情況下,客戶端是通過cookie 的方式找到伺服器上的Session的。 可以開啟自己的瀏覽器找到SESSIONID 這個cookie。裡
Safari無痕模式下,storage被禁用問題
前言 Safari開啟無痕模式後,localStorage和sessionStorage為空,對其進行set操作也會報錯,也就是說這種情況下,storage是被禁止使用了。接下來說一下解決方法。 解決方案 我們專案框架上的解決方法是對storage進行一層封裝,遇到這種開啟無痕模式的情況,會定義一個wi
RichTextBox 新增控制元件,被禁用如何處理 button
WPF中RichTextBox的確非常的強大, 但讓人很鬱悶的是:新增到其中的控制元件總是被禁用的(IsEnabled始終為false) 參考以下程式碼: <Window xmlns="http://schemas.microsoft.com/winfx/200
jmeter手寫腳本,使用正則獲取cookie(禁用cookies管理器)
coo inf 手動 全局 其他 去掉 bugfree 因此 頭信息 註:這裏以bugfree為例 1.bugfree登錄時會有重定向,這會導致每個URL都會有。因此要手動獲取cookie的時候,需要去掉重定向勾選 正則獲取動態PHPsession 獲取到值後,放到信
通過powershell查詢OU中被禁用的AD賬號,並刪除他們的所屬組
port enable memberof sele lse mov rop acc identity 這個需求可以通過兩個方向來實現1、找到禁用的賬號,刪除除domain users外的所有組,腳本內容如下 #導入AD模塊import-module ActiveDirect
解決---MISCONF Redis被配置為儲存RDB快照,但目前無法在磁碟上存留。可能修改資料集的命令被禁用。請檢查Redis日誌,瞭解有關錯誤的詳細資訊。
出現bug: 在學習celery,將資料儲存到redis時出現下面的bug。 consumer: Cannot connect to redis://192.168.12.188:6379/3: MISCONF Redis is configured to save RDB sn
session依賴cookie,如果瀏覽器禁用了cookie呢?
<form action='<%=response.encodeURL("/jsp/index.jsp") %>' method="post"> <
啟動虛擬機器會有錯誤報告:二進位制轉換與此平臺上的長模式不相容。此虛擬環境中的長模式將被禁用,因此需要使用長模式的應用程式將無法正常執行
1.先安裝VMware2.常建立虛擬機器3.啟動虛擬機器,啟動會有:二進位制轉換與此平臺上的長模式不相容。此虛擬環境中的長模式將被禁用,因此需要使用長模式的應用程式將無法正常執行 解決辦法:需要開啟BIOS系統把 Intel Virtual Technology 改為e
解決VMWare中“二進位制轉換與此平臺上的長模式不相容,此虛擬環境中的長模式將被禁用”問題
【轉自】http://blog.sina.com.cn/s/blog_63b15fc901019wkn.html 在使用Windows7 64位作業系統時,無法執行VMWare或MS Virtual server等軟體虛擬作業系統。提示為“提示:軟體虛擬化與此平臺上的長模式不相容. 禁用長模式.
關於word2016中mathtype無法使用以及“由於巨集安全設定,無法找到巨集或巨集已被禁用”的解決方案
版本描述:系統:win10 64位word: 2016版 32位Mathtype: 6.9d (6.9b也出現相同問題,應該可以通過相同的方法解決)問題描述: 自從在一次win10更新之後,word文件開啟時就會出現“由於巨集安全設定,無法找到巨集或巨集已被禁用”的提示。某些文件則提示“被另一使用者鎖定,無
使用QFileInfo類獲取檔案資訊(在NTFS檔案系統上,出於效能考慮,檔案的所有權和許可權檢查在預設情況下是被禁用的,通過qt_ntfs_permission_lookup開啟和操作。absolutePath()必須查詢檔案系統。而path()函式,可以直接作用於檔名本身,所以,path() 函
版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/Amnes1a/article/details/65444966QFileInfo類為我們提供了系統無關的檔案資訊,包括檔案的名字和在檔案系統中位置,檔案的訪問許可權,是否是目錄或符合連結,等等。並且,通過這個類
fsockopen被禁用,搞定discuz X2.5通訊,實現單點登入登出
空間安裝了discuz X2.5,安裝時提示fsockopen和pfsockopen函式被禁用,沒有理會繼續安裝,安裝過程沒出現錯誤但是進入後臺Ucenter卻發現通訊失敗,跟蹤了一下程式碼發現問題出現在uc_server/model/misc.php的9
【轉】SQL2008的sa賬戶被禁用,其他賬戶無法連線的解決方法
百度知道上搜來的,不過答案好像也是CSDN的。但我沒有找到地址,先貼出來方法備忘,侵刪。 或者你還有其它的sysadmin許可權的賬號,你可以用此賬號登入,重置SA密碼。 但是在以下情況下,怎麼辦呢? 1. SA密碼丟失或者SA賬號被禁用。 2. 你進行了一些安全操作,把B
XSS,CSRF,Cookie防劫持的處理
而是 java php xmlhttp 無效 可能 情況下 sca 憑證 Cookie與sessionHTTP天然是無狀態的協議, 為了維持和跟蹤用戶的狀態, 引入了Cookie和Session. Cookie包含了瀏覽器客戶端的用戶憑證, 相對較小. Session則維護
android開發中懸浮窗被禁用,無許可權開啟懸浮窗的解決方案
首先,感謝這兩篇博文http://blog.csdn.net/cankingapp/article/details/51569576 http://blog.csdn.net/cool_fuwei/article/details/53070232 瞭解知識:
Android檢查應用許可權是否被禁用,解決許可權被禁用時程式崩潰
一、問題描述 在Android開發中,往往會用到許多諸如攝像頭、錄音等許可權。但是,我們都知道,小米、魅族等定製系統,或者360等安全軟體在程式請求開啟相機、錄音等操作時,會先彈出對話方塊提示使用者是否允許程式執行這些操作,如果使用者選擇允許則接下來的操作一
Win10輸入法無法選擇,右下角出現叉號,提示IME被禁用
批處理來自動實現:schtasks /End /TN "\Microsoft\Windows\TextServicesFramework\MsCtfMonitor"schtasks /Run /TN "\Microsoft\Windows\TextServicesFrame