在前面的篇幅中,我們對認證和授權流程大致梳理了一遍。在這個過程中我們一直都是使用系統生成的預設頁面,登錄成功後也是直接調轉到根路徑頁面。而在實際的開發過程中,我們是需要自定義登錄頁面的,有時還會添加各類驗證機制,在登錄成功後會跳轉至指定頁面,還會進行各種美化,甚至是前後端分離的方式。這時,就需要我們... ...
在前面的篇幅中,我們對認證和授權流程大致梳理了一遍。在這個過程中我們一直都是使用系統生成的預設頁面,登錄成功後也是直接調轉到根路徑頁面。而在實際的開發過程中,我們是需要自定義登錄頁面的,有時還會添加各類驗證機制,在登錄成功後會跳轉至指定頁面,還會進行各種美化,甚至是前後端分離的方式。這時,就需要我們對自定義登錄進行實現。
本章節使用spring-security-custom-login
一、工程準備
1、pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>security-study</artifactId>
<groupId>cn.wujiwen.security</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<description>自定義登錄頁面</description>
<artifactId>spring-security-custom-login</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
</project>
我們引入了thymeleaf
,也是官方推薦的做法。
2、application.yml
server:
port: 8080
spring:
security:
user:
name: admin
password: admin
roles: ADMIN
非常的熟悉,埠、基礎用戶等信息
3、啟動類Application
@SpringBootApplication
public class SecurityLoginApplication {
public static void main(String[] args) {
SpringApplication.run(SecurityLoginApplication.class,args);
}
}
二、自定義SecurityConfig
自定義SecurityConfig
需繼承WebSecurityConfigurerAdapter
並重寫相關配置即可,由於今天只涉及到自定義頁面的信息,所以我們只需要重寫configure(HttpSecurity http)
方法即可。在重寫這個方法前,我們先來看一下原來這個方法是乾什麼的。
protected void configure(HttpSecurity http) throws Exception {
http
// 1 聲明ExpressionUrlAuthorizationConfigurer,要求所有URL必須登錄認證後才能訪問
.authorizeRequests().anyRequest().authenticated()
.and()
// 2 聲明一個預設的FormLoginConfigurer
.formLogin()
.and()
// 3 聲明一個預設的HttpBasicConfigurer
.httpBasic();
}
- 對任何請求要求用戶已認證(通俗地講,用戶必須先登錄才能訪問任何資源);
- 啟用用戶名密碼表單登錄認證機制;
- 啟用
Http Basic
認證機制;
下麵我們就通過重寫上述的方法來做到自定義登錄頁面等信息
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().anyRequest().authenticated()
.and().httpBasic().and()
// 1
.formLogin().loginPage("/login")
// 2
.loginProcessingUrl("/loginAction")
// 3
.defaultSuccessUrl("/index")
.permitAll();
}
}
我們發現其實和預設方法中並沒有太大的差別,只有三處的變化
loginPage()
中將指定自定義登錄頁面的請求路徑loginProcessingUrl()
為認證的請求介面,也就是我們常說的form
表單中的action
。如果不指定,將採用loginPage
中的值。defaultSuccessUrl()
為認證成功後跳轉的頁面地址
三、自定義頁面
在springboot中使用html頁面這裡就不過多贅述,一般情況下在resource下新建templates文件下,將需要的頁面放到該文件下即可。我的路徑為
_resource
|_templates
|_login.html
|_index.html
1、login.thml
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Spring Security Example </title>
</head>
<body>
<div th:if="${param.error}">
用戶名或密碼錯誤
</div>
<div th:if="${param.logout}">
你已經退出
</div>
<form th:action="@{/loginAction}" method="post">
<div><label> 賬號 : <input type="text" name="username"/> </label></div>
<div><label> 密碼 : <input type="password" name="password"/> </label></div>
<div><input type="submit" value="登錄"/></div>
</form>
</body>
</html>
這裡我將action與loginProcessingUrl()對應,你也可以自己嘗試更換或使用預設或與loginPage()一致的。
到這裡我們就完成了一個最簡單的表單提交的頁面了。當我們點擊submit按鈕時,正確的請求路徑將是
curl -x POST -d "username=admin&password=admin" http://127.0.0.1:8080/loginAction
這裡可能會有個疑問了,為啥你的參數就是username和password呢?嗯~ 當然可以自己指定的啊,因為在FormLoginConfigurer中預設的指定參數
public FormLoginConfigurer() {
super(new UsernamePasswordAuthenticationFilter(), null);
usernameParameter("username");
passwordParameter("password");
}
2、index.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Spring Security Example</title>
</head>
<body>
<h2>Welcome <b th:text="${username}"></b></h2>
</body>
</html>
這是個認證成功後的歡迎頁面,比較簡單,顯示當前登錄用戶即可
四、BaseContoller
上面我們定義了各類路徑和請求地址,接下來我們需要定義如果將這些頁面映射出來
@Controller
public class BaseController {
// loginPage("/login") 將跳轉到login.html
@GetMapping("/login")
public String login() {
return "login";
}
// index.html
@RequestMapping("/index")
public String index(Model model, HttpServletRequest request) {
model.addAttribute("username",request.getUserPrincipal().getName());
return "index";
}
}
五、測試
到這裡我們已經完成了一個簡單的自定義登錄頁面的改造了。當然,在實際的項目中需要自定義的東西還有很多很多,比如,當認證不通過時如果操作,當用戶退出登錄時如果操作,這些都沒有去實現。
還有人會說,這都什麼年代了,前後端分離啊,這些都可以通過一步步的改造來實現的。
(完)