spring security custom loginPage + freemarker
阿新 • • 發佈:2019-01-02
最近在做一個專案,使用spring security來做登入的身份驗證,折騰了很久,也搜了很多資料終於把這部分內容做的差不多了,在這裡來做一個總結。
專案所使用的工具有:
- Spring 4.2.2.RELEASE
- Spring Security 4.0.3.RELEASE
- MAVEN 3
- JDK 1.7
- tomcat 8
這裡有一個很簡單的使用spring-security的專案,Spring-Security-Custom-LoginPage,但是這個專案使用的是預設的登入頁面和設定,在本專案中使用的是自定義的登入頁面。
1、框架的搭建
首先需要進行Spring框架的搭建,在這裡不多做介紹,需要依賴一些基礎的spring包。
2、Spring Security Configuration
第二步需要進行Spring Security框架的搭建,首先需要在maven中依賴相應的包,分別在properties中和dependencymanagement中加入相應的內容。
<!-- spring security -->
<properties>
<spring.security.version>4.0.3.RELEASE</spring.security.version>
</properties>
<dependencyManagement >
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId >
<artifactId>spring-security-core</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
</dependencyManagement>
引用完成後需要進行Spring Security的配置,加入spring-security.xml檔案,並在web.xml中引用相應的配置檔案
<!-- web.xml -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:application*.xml,</param-value>
</context-param>
<!-- application-spring-security.xml -->
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="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 auto-config="true">
<intercept-url pattern="/login" access="permitAll"/>
<intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
<form-login login-page="/login"
login-processing-url="/login_check"
username-parameter="username"
password-parameter="password"
authentication-failure-url="/login?error"
default-target-url="/home" />
<logout logout-url="/logout"
logout-success-url="/login?logout" />
<csrf disabled="true"/>
</http>
<authentication-manager>
<authentication-provider ref="authenticationProvider"/>
<authentication-provider>
<user-service>
<user name="1" password="1" authorities="ROLE_USER"/>
</user-service>
</authentication-provider>
</beans:beans>
以下是對上述配置檔案中配置項的解釋說明
login-page="/login"
,"/login"
頁面是用來展示登入表單的頁面。login-processing-url="/login_check"
,"/login_check"
是用來form表單action所指向的路由,用來標識spring進行登入驗證時所呼叫的連結。username-parameter="username"
指定了表單中提交使用者名稱所使用input標籤的name。password-parameter
同上,用來指定提交密碼的input標籤的nameauthentication-failure-url="/login?error"
用來說明登入驗證失敗時所跳轉到的連結。default-target-url="/"
用來標識登入成功後預設跳轉到的連結。logout-url="/logout"
用來標識進行登出時所需要呼叫的連結logout-success-url="login?logout"
用來標識登出賬號成功後所跳轉到的連結<csrf disabled="true"/>
用來標識禁用csrf保護,有關csrf可以查詢其他資料,在這裡不做解釋說明。<intercept-url pattern="/login" access="permitAll"/>
這條語句用來標識哪些資源允許有哪些許可權的人訪問。<authentication-manager>
用來宣告驗證登入資訊的資源,這裡展示了兩種,一種是在xml檔案中顯式的宣告<user-service>
來生成登入使用者資訊。另外是使用類來實現AuthenticationProvider
介面並在xml中用<authentication-provider ref="aquariusAdminAuthenticationProvider"/>
引用。
3、Login Pages
<#import "/spring.ftl" as spring />
<!-- login.ftl -->
<html>
<head>
</head>
<body>
<div class="mainlogin">
<form id="login" name="login" action="<@spring.url '/login_check' />" method="POST">
<#if msg??><p class="error-msg">${msg}</p></#if>
<p><label>使用者名稱:</label><input name="username" type="text" class="txt" autofocus></p>
<p><label>密碼:</label><input name="password" type="text" class="txt wid1"></p>
<input type="submit" id="login_btn" name="submit">登入</input>
</form>
</div>
</body>
</html>
注意使用freemarker需要引用spring.ftl檔案來進行form表單action的定義。
<!-- home.ftl -->
<html>
<body>
<h1>Title : ${title}</h1>
<h1>Message : ${message}</>
</body>
</html>
很簡單的home頁面
4、Spring MVC Controller
package com.lightafire.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class HelloController {
@RequestMapping(value = { "/home" }, method = RequestMethod.GET)
public ModelAndView welcomePage(Model model) {
ModelAndView model = new ModelAndView();
model.addAttribute("title", "Spring Security Custom Login Form");
model.addAttribute("message", "This is welcome page!");
return "/home";
}
//Spring Security see this :
@RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView login(
@RequestParam(value = "error", required = false) String error,
@RequestParam(value = "logout", required = false) String logout) {
ModelAndView model = new ModelAndView();
if (error != null) {
model.addAttribute("error", "Invalid username and password!");
}
if (logout != null) {
model.addAttribute("msg", "You've been logged out successfully.");
}
return "/login";
}
}
到這裡全部設定就已經完成了,執行專案訪問/login
即可開啟登入頁面,輸入賬號,密碼usernmae:1,password:1
即可登入。
5、使用資料庫或其他資料來源進行登入驗證
需要實現之前提到的<authentication-provider ref="authenticationProvider"/>
。
@Component("authenticationProvider")
public class authenticationProvider implements AuthenticationProvider {
@Override
public boolean supports(Class<?> authentication) {
return true;
}
@Override
public Authentication authenticate(Authentication arg0) throws AuthenticationException {
// 獲取使用者名稱
String username = arg0.getName();
// 獲取密碼
String password = arg0.getCredentials().toString();
User user;
// 嘗試提取使用者資訊,在這裡通過不同方式獲取登入使用者的相關資訊並賦值給user!!!
// 驗證密碼
bool valid = user.password == password;
// 設定許可權
if (valid) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(ROLE_USER);
authorities.add(authority);
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(username, password, authorities);
auth.setDetails("login user.");
return auth;
} else {
// do something when valid failed. 可以拋異常或是進行註冊再return之類的。
}
}
}