Shiro的authc过滤器的执行流程
1.先執(zhí)行isAccessAllowed(),通過subject.isAuthenticated()判斷當(dāng)前session中的subject是否已經(jīng)登陸過。如果在當(dāng)前session即會(huì)話中已經(jīng)登陸過,返回true,authc過濾器放行請(qǐng)求到loginUrl。
問題?
這里會(huì)有一個(gè)問題,如果我登陸成功后,再次訪問loginUrl,會(huì)執(zhí)行isAccessAllowed()并返回true放行,那么我訪問到了loginUrl,如果此時(shí)我在loginUrl中輸入新的用戶名密碼,再提交則先執(zhí)行isAccessAllowed(),因?yàn)楫?dāng)前session中的subject是已經(jīng)登陸過的,isAccessAllowed()返回true,autch放行,請(qǐng)求又會(huì)到loginUrl。因?yàn)樵诘顷懙那闆r下,再訪問loginUrl則isAccessAllowed()始終返回true,不會(huì)執(zhí)行到onAccessDenied()方法,即不會(huì)驗(yàn)證請(qǐng)求中的新的用戶名和密碼。
2.如果isAccessAllowed()是false即拒絕訪問后執(zhí)行onAccessDenied()方法:
2.1判斷是否是登陸請(qǐng)請(qǐng)求(即request中的url和我們?cè)O(shè)置的loginUrl是否一致)
2.1.1如果請(qǐng)求的url和我們?cè)谂渲梦募性O(shè)置的loginUrl一樣
2.1.1.1如果是get請(qǐng)求,則返回true,即該過濾器連放行,讓請(qǐng)求訪問到loginUrl
2.1.1.2如果是post請(qǐng)求,則創(chuàng)建subjet和tocken 調(diào)用subject的login方法進(jìn)行認(rèn)證(即開始執(zhí)行realm的doGetAuthenticationInfo方法)
2.1.1.2.1如果認(rèn)證成功則會(huì)返回false阻止filterChain繼續(xù)執(zhí)行即不讓請(qǐng)求達(dá)到loginUrl,而是在這里直接重定向我們上次訪問的非logurl的請(qǐng)求地址去(這個(gè)請(qǐng)求地址在你訪問的時(shí)候已經(jīng)被保存到session中了)如果沒有上次訪問的地址,則到我們?cè)O(shè)置的SuccessUrl
2.1.1…2.2如果認(rèn)證失敗則會(huì)返回true,將認(rèn)證失敗的異常信息放到reqeust屬性中,即放行讓fliterChain繼續(xù)執(zhí)行,讓請(qǐng)求達(dá)到loginUrl。
2.2如果否即request中的url不是loginUrl,則保存請(qǐng)求(應(yīng)該是到session里),再將請(qǐng)求重定向到loginUrl(瀏覽器又會(huì)訪問通過get方法訪問loginUrl,又會(huì)被authc攔截,再重複上面流程,此時(shí)是登陸請(qǐng)求且是GET請(qǐng)求則authc會(huì)放行訪問到loginUrl),執(zhí)行完重定向后返回false阻止filterChain繼續(xù)執(zhí)行。
綜上所述:
只有以下四種情況會(huì)到loginUrl:
//1.還沒有登陸成功的情況下:get請(qǐng)求我們?cè)谂渲梦募性O(shè)置的loginUrl,authc會(huì)放行請(qǐng)求到這里
//2.還沒有登陸成功的情況下:post請(qǐng)求我們?cè)谂渲梦募性O(shè)置的loginUrl,authc在認(rèn)證失敗后會(huì)讓瀏覽器重定向到這里
//3.還沒有登陸成功的情況下:請(qǐng)求(不管post還是get)的頁面不是loginUrl且需要authc過濾,那么authc也會(huì)讓瀏覽器重定向到這里
//4.登陸成功后,瀏覽器再次訪問loginUrl(不管post或get),authc也會(huì)放行到這里。
怎么解決上面登陸成功后再訪問loginUrl,不會(huì)執(zhí)行新用戶認(rèn)證的問題呢?只有重寫authc過濾器的isAccessAllowed()方法
最后再配置文件中注冊(cè)該類,覆蓋掉shiro原本的過濾器FormAuthenticationFilter:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><property name="securityManager" ref="securityManager" /><property name="loginUrl" value="/login" /><property name="successUrl" value="/index.jsp" /><property name="unauthorizedUrl" value="/unauthorized.jsp" /><property name="filters"><map><entry key="authc" value-ref="myAuthcFilter" /></map></property><property name="filterChainDefinitions"><value># some example chain definitions:/login = authc/logout = logout/1.jsp = user/** = authc# more URL-to-FilterChain definitions here</value></property></bean>login的寫法:
@Controller public class UsersController {@RequestMapping("login")public String login(HttpServletRequest req) {//只有//1.還沒有登陸成功的情況下:get請(qǐng)求我們?cè)谂渲梦募性O(shè)置的loginUrl,authc會(huì)放行請(qǐng)求到這里//2.還沒有登陸成功的情況下:post請(qǐng)求我們?cè)谂渲梦募性O(shè)置的loginUrl,authc在認(rèn)證失敗后會(huì)讓瀏覽器重定向到這里//3.還沒有登陸成功的情況下:請(qǐng)求(不管post還是get)的頁面不是loginUrl且需要authc過濾,那么authc也會(huì)讓瀏覽器重定向到這里//4.登陸成功后,瀏覽器再次訪問loginUrl(不管post或get),authc也會(huì)放行到這里。如果我們?cè)谧远x的過濾器中//設(shè)置成如果是POST請(qǐng)求的loginUrl,我們返回false。那么post請(qǐng)求的loginUrl就會(huì)執(zhí)行在過濾器中執(zhí)行onAcessDenied()方法,如果post的loginUrl驗(yàn)證失敗了會(huì)到這里,如果驗(yàn)證成功則到secessUrl這里。String errorClassName = (String) req.getAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);if(UnknownAccountException.class.getName().equals(errorClassName)) {req.setAttribute("error", "用戶名/密碼錯(cuò)誤");} else if(IncorrectCredentialsException.class.getName().equals(errorClassName)) {req.setAttribute("error", "用戶名/密碼錯(cuò)誤");} else if(errorClassName != null) {req.setAttribute("error", "未知錯(cuò)誤:" + errorClassName);}return "login.jsp";} }session和cookie:
通過瀏覽器第一次發(fā)送http請(qǐng)求時(shí),服務(wù)器會(huì)創(chuàng)建一個(gè)session和cookie(cookie中保存sessionid),這個(gè)session服務(wù)器的默認(rèn)時(shí)間30分鐘,可以設(shè)置。服務(wù)第一次響應(yīng)時(shí)也把cookie放到響應(yīng)中給瀏覽器,瀏覽器
收到cookie后,會(huì)判斷cookie有沒有設(shè)置過期時(shí)間,如果沒有則只保存在內(nèi)存中。如果有則存到硬盤里。
如果只是保存到內(nèi)存中,服務(wù)器端的session依然會(huì)保留30分鐘。那么瀏覽器一關(guān)閉,cookie消失,sessionid也消失了。。但此時(shí)打開瀏覽器再訪問服務(wù)器時(shí),雖然服務(wù)器的session依然存在,但瀏覽器中的cookie(sessionid)消失了
瀏覽器發(fā)送的請(qǐng)求頭里沒有cookie(沒有sessionid),服務(wù)器會(huì)當(dāng)作一個(gè)新的請(qǐng)求,會(huì)再創(chuàng)建一個(gè)新session。服務(wù)器中的之前的session 30分鐘侯清除。
如果保存到硬盤里了, 服務(wù)器端的session依然會(huì)保留30分鐘。那么關(guān)閉瀏覽器后,再打開瀏覽器訪問服務(wù)器時(shí),瀏覽器會(huì)找到存到硬盤里的cookie(sessionId), 瀏覽器再次請(qǐng)求服務(wù)器時(shí)會(huì)帶上cookie,服務(wù)器收到請(qǐng)求后發(fā)現(xiàn)有cookie(sessionId)并且服務(wù)器
端的session也存在。那么服務(wù)器就依然會(huì)使用之前的session。不會(huì)再創(chuàng)建一個(gè)新的session。
所以session默認(rèn)關(guān)閉瀏覽器就失效了。
總結(jié)
以上是生活随笔為你收集整理的Shiro的authc过滤器的执行流程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言编程跑马灯,走楼灯设计(C语言设计
- 下一篇: 西南科技大学OJ题 单链表中信息的分