spring security起步三:自定義登錄配置與form-login屬性詳解

在上一篇博客spring security起步二:自定義登錄頁中我們實現瞭如何自定義登錄頁,但是還存在很多問題:
1.spring security如何對登錄請求進行攔截
2.登錄成功後如何跳轉
3.登錄失敗後如何跳轉

form-login屬性詳解

form-login是spring security命名空間配置登錄相關信息的標籤,它包含如下屬性:
1. login-page 自定義登錄頁url,默認爲/login
2. login-processing-url 登錄請求攔截的url,也就是form表單提交時指定的action
3. default-target-url 默認登錄成功後跳轉的url
4. always-use-default-target 是否總是使用默認的登錄成功後跳轉url
5. authentication-failure-url 登錄失敗後跳轉的url
6. username-parameter 用戶名的請求字段 默認爲userName
7. password-parameter 密碼的請求字段 默認爲password
8. authentication-success-handler-ref 指向一個AuthenticationSuccessHandler用於處理認證成功的請求,不能和default-target-url還有always-use-default-target同時使用
9. authentication-success-forward-url 用於authentication-failure-handler-ref
10. authentication-failure-handler-ref 指向一個AuthenticationFailureHandler用於處理失敗的認證請求
11. authentication-failure-forward-url 用於authentication-failure-handler-ref
12. authentication-details-source-ref 指向一個AuthenticationDetailsSource,在認證過濾器中使用

spring security登錄相關的過濾器

首先應注意的一點是,spring security 3.x 默認的登錄攔截URL是/j_spring_security_check,而spring security 4.x默認攔截的URL是/login。在spring security中,具體處理表單登錄驗證的是o.s.s.w.a.UsernamePasswordAuthenticationFilter,另外一個過濾器o.s.s.w.a.ui.DefaultLoginPageGeneratingFilter用於在沒有指定登錄頁時動態生成一個默認登錄頁

登錄配置

登錄頁面 login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body onload='document.f.username.focus();'>
    <h3>Login with Username and Password</h3>
    <form name='f' action='${pageContext.request.contextPath }/login'
        method='POST'>
        <table>
            <tr>
                <td>User:</td>
                <td><input type='text' name='username' value=''></td>
            </tr>
            <tr>
                <td>Password:</td>
                <td><input type='password' name='password' /></td>
            </tr>
            <tr>
                <td colspan='2'><input name="submit" type="submit"
                    value="Login" /></td>
            </tr>
        </table>
    </form>
</body>
</html>

登錄成功頁面 index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    登錄成功
</body>
</html>
登錄失敗頁面 login-failure.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    登錄失敗
</body>
</html>

頁面配置完成,剩下的就是映射url到具體的頁面

登錄成功頁面映射 HelloController.java
@Controller
public class HelloController {

    @RequestMapping(value={"/welcome","/"},method=RequestMethod.GET)
    public String welcome(){
        return "index";
    }
}
登錄頁面及登錄失敗頁面映射 LoginController.java
@Controller
public class LoginController {

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String loginPage(@RequestParam(value = "error", required = false) String error, Model model) {
        if (error != null) {
            return "login-failure";
        }
        return "login";
    }
}
spring security配置 spring-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<bean:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:bean="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">

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

    <http auto-config="true" use-expressions="true">
        <intercept-url pattern="/*" access="hasRole('ROLE_USER')" />
        <form-login login-page="/login" login-processing-url="/login" always-use-default-target="true"
            default-target-url="/welcome" authentication-failure-url="/login?error=error" />
    </http>
    <authentication-manager alias="authenticationManager">
        <authentication-provider>
            <user-service>
                <user authorities="ROLE_USER" name="guest" password="guest" />
            </user-service>
        </authentication-provider>
    </authentication-manager>

</bean:beans>

現在,配置基本完成,啓動項目後,在登錄頁面輸入用戶名和密碼,不管正確與否都會有405錯誤Request method ‘POST’ not supported。爲什麼會出現這個錯誤呢?

登錄請求405錯誤

在登錄請求中出現405錯誤,其實是我們在配置過程中,spring mvc和spring security出現了一點衝突導致的。

首先,請注意下面這兩個配置段

<http pattern="/login" security="none"></http>
<form-login login-page="/login" login-processing-url="/login" ......

第一個配置告訴spring security,類似於/login的url請求不做過濾處理,而第二個配置信息又告訴spring security url爲/login的post請求登錄請求處理。正是這種衝突導致了405錯誤的發生。

既然知道了錯誤原因,那麼只要避免衝突就能解決這個問題:使登錄頁的請求和登錄處理的請求不一致,然後只配置登錄頁的請求不做攔截處理.

我採用的方法是使用默認的登錄URL /login,修改登錄頁面跳轉url爲/loginPage。請自行修改代碼和配置信息

這樣是不是就大工告成了呢?很遺憾,當你啓動程序時,輸出用戶名和密碼,不管正確與否,都會有404 Not Found等着你,這又是爲什麼呢?

登錄請求404錯誤

首先,建議你看一下spring security自動生成的登錄頁源碼,你會發現有如下代碼

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />

對於什麼是csrf,請自行參考網上的資料。

spring security默認情況下csrf protection是開啓的,由於我們的登錄頁沒有配置csrf的相關信息,因此spring security內置的過濾器將此鏈接置爲無效鏈接

解決辦法就是配置csrf protection爲不可用狀態,在配置文件中增加

<csrf disabled="true"/>

附上完整的spring-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<bean:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:bean="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">

    <http pattern="/loginPage" security="none"></http>

    <http auto-config="true" use-expressions="true">
        <intercept-url pattern="/*" access="hasRole('ROLE_USER')" />
        <form-login login-page="/loginPage" login-processing-url="/login" always-use-default-target="true"
            default-target-url="/welcome" authentication-failure-url="/loginPage?error=error" />
            <csrf disabled="true"/>
    </http>
    <authentication-manager alias="authenticationManager">
        <authentication-provider>
            <user-service>
                <user authorities="ROLE_USER" name="guest" password="guest" />
            </user-service>
        </authentication-provider>
    </authentication-manager>

</bean:beans>

到此爲止,大功告成

源碼下載

源碼下載地址https://github.com/SmallBadFish/spring_security_demo/archive/0.1.1-customlogin.zip

發佈了41 篇原創文章 · 獲贊 89 · 訪問量 31萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章