spring mvc 登錄驗(yàn)證的兩種方式。

最近碰到一個(gè)需求,就是在原有的spring mvc框架上添加登錄驗(yàn)證的功能,有兩種實(shí)現(xiàn)方式:

1、Spring security

????? 在原有的spring框架上,配置Spring security的攔截器,web.xml配置如下:


<!-- 通過全局參數(shù)來(lái)引入配置文件-->

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>classpath:spring-security.xml</param-value>

</context-param>

<!-- 對(duì)靜態(tài)資源的配置 -->

<servlet-mapping>

<servlet-name>default</servlet-name>

<url-pattern>*.jpg</url-pattern>

</servlet-mapping>...

<!--委派代理過濾器-->

<filter>

<filter-name>springSecurityFilterChain</filter-name>

<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>

</filter>

<filter-mapping>

<filter-name>springSecurityFilterChain</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

??? Spring security 配置如下:

<!-- 頁(yè)面放行,不攔截-->

<security:http pattern="/login/showLogin" security="none"></security:http>

<security:http pattern="/scripts/**" security="none"></security:http>

...

<security:http auto-config="true" use-expressions="false">

<!-- 配置攔截的請(qǐng)求,任何請(qǐng)求地址都必須有ROLE_USER的權(quán)限-->

? <security:intercept-url pattern="/**" access="ROLE_USER"/>

<!-- login-page:指定登陸頁(yè)面

??????? login-processing-url:登陸請(qǐng)求路徑,登陸時(shí)必須使用該路徑

??????? default-target-url:登陸成功后進(jìn)入的頁(yè)面-->

? <security:form-login login-page="/login/showLogin"

? ? ? ? ? ? ? ? ? login-processing-url="/login"

? ? ? ? ? ? ? ? ? default-target-url="/login/userList"

? ? ? ? ? ? ? ? ? authentication-failure-url="/warehouse/main"

? ></security:form-login>

<!-- 關(guān)閉跨站請(qǐng)求偽造-->

? <security:csrf disabled="true"></security:csrf>

<!-- 退出-->

? <security:logout invalidate-session="true" logout-url="/logout" logout-success-url="/login/showLogin"></security:logout>

</security:http>


???? mvc.xml里配置攔截器,就不貼出來(lái)了。

優(yōu)點(diǎn):

???? spring security可實(shí)現(xiàn)加密認(rèn)證等,默認(rèn)的登錄認(rèn)證是通過提交表單實(shí)現(xiàn)的,可根據(jù)實(shí)際需求改為js提交認(rèn)證,如下:

<button style="width:200px;height:100px;font-size:1.5em" onclick="sub();return false;" >登 錄</button>

? ? ? ??? 用自定義按鈕替代“submit”按鈕,且需要return false,否則表單會(huì)自動(dòng)提交,在完成邏輯認(rèn)證后,可用$("#XX").submit();實(shí)現(xiàn)表單提交,“XX”是form表單的id。

缺點(diǎn):

?????? Spring security登錄驗(yàn)證必須通過連接數(shù)據(jù)庫(kù)做校驗(yàn),假設(shè)項(xiàng)目要求數(shù)據(jù)庫(kù)不在本系統(tǒng)管轄,即無(wú)法直連數(shù)據(jù)庫(kù),則該方式不適合登錄驗(yàn)證,就需要用下面的方式——token認(rèn)證。

2、token認(rèn)證

??? 俗稱登錄票,即用戶登錄時(shí)需要通過token來(lái)進(jìn)行校驗(yàn),一般放到http的header里,常用的加密方式有jwt加密。但在實(shí)際應(yīng)用過程中發(fā)現(xiàn)了一個(gè)問題,就是前端跳轉(zhuǎn)頁(yè)面的時(shí)候不會(huì)把token帶到后臺(tái),跳轉(zhuǎn)的時(shí)候用了幾種方式:1、ajax,ajax可以將token添加到header里,但是必須得有返回值,所以還是得在返回成功后在前端跳轉(zhuǎn);2、window.location.href,該方法跳轉(zhuǎn)的時(shí)候會(huì)自動(dòng)進(jìn)入到后端的controller里,然后通過controller實(shí)現(xiàn)跳轉(zhuǎn),但無(wú)法攜帶token。

??? 嘗試過不通過controller(即html或jsp文件不放在WEB-INF下),直接跳轉(zhuǎn),一樣無(wú)法攜帶token,故推測(cè)應(yīng)該是框架的問題。最后選擇了個(gè)折衷的辦法,在前端實(shí)現(xiàn)驗(yàn)證,在登錄完成后,會(huì)將token存在一個(gè)全局的地方,如localStorage;在每次訪問一個(gè)新頁(yè)面的時(shí)候,就會(huì)檢測(cè)是否登錄,即檢測(cè)token,沒有的話,就跳轉(zhuǎn)到登錄頁(yè)面。思路參考于由前端登錄驗(yàn)證,頁(yè)面跳轉(zhuǎn),攜帶headers token引發(fā)的思考和嘗試 - southday - 博客園。

??? 簡(jiǎn)單的說(shuō),就是封裝一個(gè)js,每次刷新頁(yè)面的時(shí)候調(diào)用該請(qǐng)求,admin-index.js如下:

$(function() {

axios({

???? method:'post',

???? url:'/login/info',

???? headers: {'token':getAdminToken()}

}).then(function(resp) {

???? if (!resp.data){

???????? window.location.href ="/login/showLogin";

????? }

? ? }).catch(function(error) {

????? console.log(error)

})

})

??? common.js如下:

/**

* 從localStorage中獲取adminToken

* @returns {string}

*/

function getAdminToken() {

??? return localStorage.getItem("adminToken")

}

/**

* 將adminToken保存到localStorage中

* @param token

*/

function saveAdminToken(token) {

??? localStorage.setItem("adminToken", token)

}

/**

* 將admin保存到localStorage

* @param admin

*/

function saveAdmin(admin) {

???? localStorage.setItem("admin", ($.isEmptyObject(admin) ?null :JSON.stringify(admin)))

}

/**

* 從localStorage中取user

* @returns {admin}

*/

function getAdmin() {

???? var a =localStorage.getItem("admin")

??? return $.isEmptyObject(a) ?null :JSON.parse(a)

}

/**

* 清空l(shuí)ocalStorage

*/

function clearStorage() {

???? localStorage.clear();

}

??? jsp頁(yè)面引用時(shí),只需如下添加即可:

<script type="text/javascript" src="<c:url value="/scripts/axios.min.js"/>" ></script>

<script type="text/javascript" src="<c:url value="/scripts/admin-index.js"/>" ></script>

<script type="text/javascript" src="<c:url value="/scripts/common.js"/>" ></script>

?????? 這樣可以實(shí)現(xiàn)訪問新頁(yè)面時(shí),如果沒有登錄則自動(dòng)跳轉(zhuǎn)到登錄頁(yè)面,但細(xì)想其實(shí)還存在一個(gè)問題,就是前端無(wú)法實(shí)現(xiàn)token的過期驗(yàn)證,目前還沒有較好的辦法,如果有后續(xù)會(huì)更新上來(lái),所以如果還想從根源上解決問題,還是需要選擇一個(gè)合適的框架,前端跳轉(zhuǎn)的時(shí)候自帶有路由功能。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容