1、簡介
常見的兩個安全框架shiro|spring security,這里只介紹spring security;
Spring Security是針對Spring項目的安全框架,也是Spring Boot底層安全模塊默認的技術選型。他可以實現強大的web安全控制。對於安全控制,我們僅需引入spring-boot-starter-security模塊,進行少量的配置,即可實現強大的安全管理。
幾個類:
WebSecurityConfigurerAdapter:自定義Security策略
AuthenticationManagerBuilder:自定義認證策略
@EnableWebSecurity:開啟WebSecurity模式
應用程序的兩個主要區域是“認證”和“授權”(或者訪問控制)。這兩個主要區域是Spring Security 的兩個目標。
“認證”(Authentication),是建立一個他聲明的主體的過程(一個“主體”一般是指用戶,設備或一些可以在你的應用程序中執行動作的其他系統)
“授權”(Authorization)指確定一個主體是否允許在你的應用程序執行一個動作的過程。為了抵達需要授權的店,主體的身份已經有認證過程建立。
2、測試安全登錄&認證&授權
1、導入依賴
測試環境說明:
springboot:2.2.0、thyemelaf:3.0.11.RELEASE、
<!--引入spring security模塊-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--thyemelaf模塊-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2、配置spring security配置類
該類要用@EnableWebSecurity標注並且繼承WebSecurityConfigurerAdapter
public class MySecurityConfig extends WebSecurityConfigurerAdapter{
}
3、控制請求的訪問權限
重寫protected void configure(HttpSecurity http)方法
定制請求的授權規則:
//開啟自動配置的登錄功能,如果沒有登錄,沒有權限就會來到登錄頁面
/*formLogin() * 1、/login 來到登錄頁面 * 2、重定向到/login?error表示登錄失敗 * 3、更多詳細規定 * 4、默認post形式的/login代表處理登錄 * 5、一旦定制loginpage:那么loginPage的post請求就是登錄 * */
http.formLogin()
詳細代碼:
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
//定制請求的授權規則
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("VIP1")
.antMatchers("/level2/**").hasRole("VIP2")
.antMatchers("/level3/**").hasRole("VIP3");
//開啟自動配置的登錄功能,如果沒有登錄,沒有權限就會來到登錄頁面
/*formLogin() * 1、/login 來到登錄頁面 * 2、重定向到/login?error表示登錄失敗 * 3、更多詳細規定 * 4、默認post形式的/login代表處理登錄 * 5、一旦定制loginpage:那么loginPage的post請求就是登錄 * */
http.formLogin()
.usernameParameter("user")
.passwordParameter("pwd ")
.loginPage("/userlogin");
}
4、定制授權規則
重寫:protected void configure(AuthenticationManagerBuilder auth)
這里主要從auth.inMemoryAuthentication 從內存中獲取,如果從硬盤查看密碼的話,注意:Spring security 5.0中新增了多種加密方式,也改變了密碼的格式。請看此博客:https://blog.csdn.net/canon_in_d_major/article/details/79675033
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//inMemoryAuthentication 從內存中獲取
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("1").password(new BCryptPasswordEncoder().encode("123")).roles("VIP1","VIP2")
.and()
.withUser("2").password(new BCryptPasswordEncoder().encode("123")).roles("VIP2","VIP3")
.and()
.withUser("3").password(new BCryptPasswordEncoder().encode("123")).roles("VIP2","VIP3");
}
3、測試權限控制&注銷
1、注銷功能
開啟自動配置的注銷功能 1、訪問/loginout表示用戶注銷,清空session 2、注銷成功之后,會返回login?logout
http.logout().logoutSuccessUrl("/");//注銷成功之后來到首頁
html這樣寫:
<form th:action="@{/logout}" method="post">
<input type="submit" value="注銷">
</form>
當頁面點擊注銷按鈕,會跳到登錄頁面,logoutSuccessUrl("/")可到指定位置
2、權限控制
這里可以指定特定用戶訪問相對應的信息,不同角色顯示不同內容
引入thymeleaf-extras-springsecurity5依賴
<!--引入>thymeleaf-extras-springsecurity5-->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
這里:記錄springBoot2.2.0版本里添加thymeleaf-extras-springsecurity4后,也無法正常讀取到sec標簽
html命名空間:
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
即可解決
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1 align="center">歡迎光臨武林秘籍管理系統</h1>
<!--未認證-->
<div sec:authorize="!isAuthenticated()">
<h2 align="center">游客您好,如果想查看武林秘籍 <a th:href="@{/userlogin}">請登錄</a></h2>
</div>
<!--已認證-->
<div sec:authorize="isAuthenticated()">
<h2><span sec:authentication="name"></span>,您好,您的角色有:
<span sec:authentication="principal.authorities"></span>
</h2>
<form th:action="@{/logout}" method="post">
<input type="submit" value="注銷">
</form>
</div>
<hr>
<div sec:authorize="hasRole('VIP1')">
<h3>普通武功秘籍</h3>
<ul>
<li><a th:href="@{/level1/1}">羅漢拳</a></li>
<li><a th:href="@{/level1/2}">武當長拳</a></li>
<li><a th:href="@{/level1/3}">全真劍法</a></li>
</ul>
</div>
<div sec:authorize="hasRole('VIP2')">
<h3>高級武功秘籍</h3>
<ul>
<li><a th:href="@{/level2/1}">太極拳</a></li>
<li><a th:href="@{/level2/2}">七傷拳</a></li>
<li><a th:href="@{/level2/3}">梯雲縱</a></li>
</ul>
</div>
<div sec:authorize="hasRole('VIP3')">
<h3>絕世武功秘籍</h3>
<ul>
<li><a th:href="@{/level3/1}">葵花寶典</a></li>
<li><a th:href="@{/level3/2}">龜派氣功</a></li>
<li><a th:href="@{/level3/3}">獨孤九劍</a></li>
</ul>
</div>
</body>
</html>
4、測試記住我&定制登錄頁
1、記住我
登錄成功以后,將cookie發給瀏覽器保存,以后訪問頁面會帶上這個cookie,只要通過檢查就可以實現免登陸,點擊注銷會刪除cookie
/* * 登錄成功以后,將cookie發給瀏覽器保存,以后訪問頁面會帶上這個cookie,只要通過檢查就可以實現免登陸 * 點擊注銷會刪除cookie * */
http.rememberMe().rememberMeParameter("remember");
2、定制登錄頁
spring security默認訪問/login,
http.formLogin()
.usernameParameter("user")
.passwordParameter("pwd")
.loginPage("/userlogin");
這時候點登錄會到自己定制的登錄頁,這里要提交登錄的用戶名和密碼 ,loginPage()—>默認post形式的/login代表處理登錄,
一旦定制loginpage:那么loginPage的post請求就是登錄
登錄頁:
<div align="center">
<form th:action="@{/userlogin}" method="post">
用戶名:<input name="user"/><br>
密碼:<input name="pwd"><br/>
remember me:<input type="checkbox" name="remember">
<input type="submit" value="登陸">
</form>
</div>