本文筆記跟隨于遇見狂神說老師的視頻
一.SpringSecurity(安全)
1.相關概念
在web開發中,安全第一位,有簡單的方法,比如:攔截器,過濾器
也有安全框架,比如:SpringSecurity,shiro,兩者很像,名字和類不一樣。
都是做認證和授權兩個部分!
常見的權限有:功能權限,訪問權限,菜單權限。以前做這些用攔截器,過濾器(大量的原生代碼~)
?2.代碼前期準備階段
2.1導入靜態資源
2.2導入security依賴
<!--SpringSecurity --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>
2.3創建controller層
package com.zhang.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@Controller
public class RouterController {@GetMapping("/index")public String index(){return "index";}@GetMapping("/tologin")public String toLogin(){return "views/login";}@GetMapping("/level1/{id}")public String level1(@PathVariable("id") int id){return "views/level1/"+id;}@GetMapping("/level2/{id}")public String level2(@PathVariable("id") int id){return "views/level2/"+id;}@GetMapping("/level3/{id}")public String level3(@PathVariable("id") int id){return "views/level3/"+id;}
}
3.認證和授權實現
?創建一個配置類,用來設置用戶的訪問權限,以及認證用戶的身份信息
package com.zhang.config;import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter {//授權@Overrideprotected void configure(HttpSecurity http) throws Exception {//給傳過來的url設置訪問權限,首頁所有人都可以訪問,功能頁只能是有權限的人可以訪問//請求授權的規則http.authorizeRequests().antMatchers("/").permitAll().antMatchers("/level1/**").hasRole("vip1").antMatchers("/level2/**").hasRole("vip2").antMatchers("/level3/**").hasRole("vip3");//沒有權限自動跳到登錄頁面http.formLogin();}//認證 springboot 2.1.x可以直接使用//Spring security 5.0中新增了多種加密方式,也改變了密碼的格式。//要想我們的項目還能夠正常登陸,需要修改一下configure中的代碼。我們要將前端傳過來的密碼進行某種方式加密//spring security 官方推薦的是使用bcrypt加密方式。@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {//可以從內存也可以從數據庫中取數據認證auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("zhangsan").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1").and().withUser("lisi").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2").and().withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3");}
}
4.注銷功能實現
在配置類中實現注銷功能
在前端index.xml主頁面中增加注銷按鈕
經測試,注銷成功后會跳轉到登錄頁面,如果想要注銷成功后跳轉到主頁面,需要在配置類中改進一下開啟注銷功能
//開啟注銷功能 .logoutSuccessUrl("/"); 注銷成功來到首頁http.logout().logoutSuccessUrl("/");
如果用戶沒有登錄時在導航欄只顯示登錄按鈕,登錄后在導航欄顯示用戶的登錄信息和注銷按鈕并且如何根據用戶的權限不同在菜單欄顯示的功能也不同?
我們需要結合thymeleaf中的一些功能
sec:authorize=“isAuthenticated()”:是否認證登錄!來顯示不同的頁面
導入maven依賴
<!--security-thymeleaf整合包--><dependency><groupId>org.thymeleaf.extras</groupId><artifactId>thymeleaf-extras-springsecurity4</artifactId><version>2.1.2.RELEASE</version></dependency>
導入以上依賴后,可以在thymeleaf中進行一些security的操作
修改前端index.xml主頁面
導入命名空間:
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"
修改導航欄,增加認證判斷:?
<!--主容器-->
<div class="ui container"><div class="ui segment" id="index-header-nav" th:fragment="nav-menu"><div class="ui secondary menu"><a class="item" th:href="@{/index}">首頁</a><!--登錄注銷--><div class="right menu"><!--如果未登錄--><div sec:authorize="!isAuthenticated()"><a class="item" th:href="@{/toLogin}"><el-button type="success" icon="el-icon-check" circle></el-button> 登錄</a></div><!--如果已登錄--><div sec:authorize="isAuthenticated()"><a class="item"><el-button type="primary" icon="el-icon-edit" circle></el-button>用戶名:<span sec:authentication="principal.username"></span></a></div><a class="item" th:href="@{/logout}"><el-button type="danger" icon="el-icon-delete" circle></el-button> 注銷</a></div></div></div>
重啟后點擊注銷會報404的錯誤,是因為它默認防止csrf跨站請求偽造,因為會產生安全問題,我們可以將請求改為post表單提交,或者在spring security中關閉csrf功能
http.csrf().disable();//關閉csrf功能:跨站請求偽造,默認只能通過post方式提交logout請求
到此,可以在導航欄正確的顯示登錄前后的信息,接下來實現根據用戶權限不同,在菜單欄顯示不同頁面。
修改前端index.xml主頁面
sec:authorize=“hasRole()”,為具有相應權限的用戶設置可訪問的頁面
5.記住我及首頁定制
5.1記住我功能實現
登錄之后,關閉瀏覽器,登錄記錄就沒了,如果關閉瀏覽器再打開,還要顯示登錄的記錄,我們需要設置一個記住我的功能。
在配置類中添加以下代碼:
//實現記住我的功能http.rememberMe();
重啟項目,登錄頁多了一個記住我功能,關閉瀏覽器后重新打開,發現登錄記錄還存在。
檢查cookie發現,記住我被保存在cookie中,點擊注銷按鈕后,cookie中的記住我被刪除
結論:登錄成功后,將cookie發送給瀏覽器保存,以后登錄帶上這個cookie,只要通過檢查就可以免登錄了。如果點擊注銷,則會刪除這個cookie?。
5.2定制登錄頁
改變spring security默認的登錄頁為自定義的登錄頁
在剛才的登錄配置功能后添加logininpage
//沒有權限自動跳到登錄頁面http.formLogin().loginPage("/tologin");
前端也要指向我們自定義的login請求
?我們登錄,需要將這些信息發送到哪里,我們也需要配置,login.html 配置提交請求及方式,方式必須為post:
<form th:action="@{/usr/tologin}" method="post">
圖片實例:
?如果前端傳遞的參數username和password不是默認的,需要我們后臺處理一下
如果username和password是以下的內容
需要在配置類中設置一下,將對應的字段進行連接
//沒有權限自動跳到登錄頁面http.formLogin().usernameParameter("/name").passwordParameter("/pwd").loginPage("/tologin");
?在登錄頁中增加記住我的按鈕
<div class="field"><input type="checkbox" name="remeber">記住我</div>
//實現記住我的功能http.rememberMe().rememberMeParameter("remeber");