javascript
SpringSecurity认证
一、 Spring Security簡介
1 概括
Spring Security是一個高度自定義的安全框架。利用Spring IoC/DI和AOP功能,為系統提供了聲明式安全訪問控制功能,減少了為系統安全而編寫大量重復代碼的工作。
使用Spring Secruity的原因有很多,但大部分都是發現了javaEE的Servlet規范或EJB規范中的安全功能缺乏典型企業應用場景。同時認識到他們在WAR或EAR級別無法移植。因此如果你更換服務器環境,還有大量工作去重新配置你的應用程序。使用Spring Security 解決了這些問題,也為你提供許多其他有用的、可定制的安全功能。
正如你可能知道的兩個應用程序的兩個主要區域是“認證”和“授權”(或者訪問控制)。這兩點也是Spring Security重要核心功能。“認證”,是建立一個他聲明的主體的過程(一個“主體”一般是指用戶,設備或一些可以在你的應用程序中執行動作的其他系統),通俗點說就是系統認為用戶是否能登錄。“授權”指確定一個主體是否允許在你的應用程序執行一個動作的過程。通俗點講就是系統判斷用戶是否有權限去做某些事情。
2 歷史
Spring Security 以“The Acegi Secutity System for Spring” 的名字始于2003年年底。其前身為acegi項目。起因是Spring開發者郵件列表中一個問題,有人提問是否考慮提供一個基于Spring的安全實現。限制于時間問題,開發出了一個簡單的安全實現,但是并沒有深入研究。幾周后,Spring社區中其他成員同樣詢問了安全問題,代碼提供給了這些人。2004年1月份已經有20人左右使用這個項目。隨著更多人的加入,在2004年3月左右在sourceforge中建立了一個項目。在最開始并沒有認證模塊,所有的認證功能都是依賴容器完成的,而acegi則注重授權。但是隨著更多人的使用,基于容器的認證就顯現出了不足。acegi中也加入了認證功能。大約1年后acegi成為Spring子項目。
在2006年5月發布了acegi 1.0.0版本。2007年底acegi更名為Spring Security。
二、 自定義登錄邏輯(數據庫訪問方式)
1 新建數據庫表結構
create table user(id bigint primary key auto_increment,username varchar(20) unique not null,password varchar(20) );insert into user values(1,'張三','zs'); insert into user values(2,'李四','ls');create table role(id bigint primary key auto_increment,name varchar(20) );insert into role values(1,'管理員'); insert into role values(2,'普通用戶');create table role_user(uid bigint,rid bigint );insert into role_user values(1,1); insert into role_user values(2,2);create table menu(id bigint primary key auto_increment,name varchar(20),url varchar(100),parentid bigint,permission varchar(20));insert into menu values(1,'系統管理','',0,'menu:sys'); insert into menu values(2,'用戶管理','',0,'menu:user');create table role_menu(mid bigint,rid bigint );insert into role_menu values(1,1); insert into role_menu values(2,1); insert into role_menu values(2,2);2 在項目中添加依賴
添加MyBatis相關依賴
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.1</version> </dependency> <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.48</version> </dependency> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId> </dependency>3 編寫配置文件
在配置文件中添加Mybatis配置
spring:datasource:username: rootpassword: 1234driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/security# 加載mapper文件路徑 mybatis:mapper-locations: classpath:mybatis/*.xml # 別名 mybatis: type-aliases-package: com.bjsxt.springscuritydemo.pojo4 新建Mapper
新建com.bjsxt.springscuritydemo.mapper.UserMapper
//告訴Spring boot當前類為Mybatis的接口類 @Mapper @Component public interface UserMapper {User selectByUsername(String username); }5 修改自定義service邏輯
修改com.bjsxt.springscuritydemo.service.impl.MyUserDetailsServiceImpl
@Service public class MyUserDetailsServiceImpl implements UserDetailsService {@Autowiredprivate UserMapper userMapper;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {User user = userMapper.selectByUsername(username);if(user==null){throw new UsernameNotFoundException("用戶名不存在");}return new org.springframework.security.core.userdetails.User(username,user.getPassword(),AuthorityUtils.commaSeparatedStringToAuthorityList("隨意給的權限"));} }三、 自定義登錄頁面
雖然Spring Security給我們提供了登錄頁面,但是對于實際項目中,大多喜歡使用自己的登錄頁面。所以Spring Security中不僅僅提供了登錄頁面,還支持用戶自定義登錄頁面。實現過程也比較簡單,只需要修改配置類即可。
1 編寫登錄頁面
編寫登錄頁面,登錄頁面中<form>的action不編寫對應控制器也可以。
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>內容</title> </head> <body> <form action="/login" method="post"><input type="text" name="username"/><input type="password" name="password"/><input type="submit" value="提交"/> </form></body> </html>2 修改配置類
修改配置類中主要是設置哪個頁面是登錄頁面。配置類需要繼承WebSecurityConfigurerAdapter,并重寫configure方法。
successForwardUrl()登錄成功后跳轉地址
loginPage() 登錄頁面
loginProcessingUrl 登錄頁面表單提交地址,此地址可以不真實存在。
antMatchers():匹配內容
permitAll():允許
3 編寫控制器
編寫控制器,當用戶登錄成功后跳轉toMain控制器。編寫完成控制器后編寫main.html。頁面中隨意寫上一句話表示main.html頁面內容即可。而之前的/login控制器方法是不執行的,所以可以刪除了。
@Controller public class LoginController {// 該方法不會被執行 // @RequestMapping("/login") // public String login(){ // System.out.println("執行了login方法"); // return "redirect:main.html"; // }@PostMapping("/toMain")public String toMain(){return "redirect:/main.html";} }四、 認證過程其他常用配置
1 失敗跳轉
表單處理中成功會跳轉到一個地址,失敗也可以跳轉到一個地址中。
1.1 編寫頁面
在src/main/resources/static下新建fail.html并編寫如下內容
1.2 修改表單配置
在配置方法中表單認證部分添加failureForwardUrl()方法,表示登錄失敗跳轉的url。此處依然是POST請求,所以跳轉到可以接收POST請求的控制器/fail中。
// 表單認證 http.formLogin().loginProcessingUrl("/login") //當發現/login時認為是登錄,需要執行UserDetailsServiceImpl.successForwardUrl("/toMain") //此處是post請求.failureForwardUrl("/fail") //登錄失敗跳轉地址.loginPage("/login.html");1.3 添加控制器方法
在控制器類中添加控制器方法,方法映射路徑/fail。此處要注意:由于是POST請求訪問/fail。所以如果返回值直接轉發到fail.html中,及時有效果,控制臺也會報警告,提示fail.html不支持POST訪問方式。
@PostMapping("/fail") public String fail(){return "redirect:/fail.html"; }1.4 設置fail.html不需要認證
認證失敗跳轉到fail.html頁面中,所以必須配置fail.html不需要被認證。需要修改配置類中內容
2 設置請求賬戶和密碼的參數名
2.1 源碼簡介
當進行登錄時會執行UsernamePasswordAuthenticationFilter過濾器。
usernamePasrameter:賬戶參數名
passwordParameter:密碼參數名
postOnly=true:默認情況下只允許POST請求。
2.2 修改配置
// 表單認證 http.formLogin().loginProcessingUrl("/login") //當發現/login時認為是登錄,需要執行UserDetailsServiceImpl.successForwardUrl("/toMain") //此處是post請求.failureForwardUrl("/fail") //登錄失敗跳轉地址.loginPage("/login.html").usernameParameter("myusername").passwordParameter("mypassword");2.3 修改頁面
修改login.html中賬戶參數名和密碼參數名
<form action = "/login" method="post">用戶名:<input type="text" name="myusername"/><br/>密碼:<input type="password" name="mypassword"/><br/><input type="submit" value="登錄"/> </form>3 自定義登錄成功處理器
3.1 源碼分析
使用successForwardUrl()時表示成功后轉發請求到地址。內部是通過successHandler()方法進行控制成功后交給哪個類進行處理
ForwardAuthenticationSuccessHandler內部就是最簡單的請求轉發。由于是請求轉發,當遇到需要跳轉到站外或在前后端分離的項目中就無法使用了。
當需要控制登錄成功后去做一些事情時,可以進行自定義認證成功控制器。
3.2 代碼實現
3.2.1 自定義類
新建類com.bjsxt.handler.MyAuthenticationSuccessHandler編寫如下:
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {@Overridepublic void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {//Principal 主體,存放了登錄用戶的信息User user = (User)authentication.getPrincipal();System.out.println(user.getUsername());System.out.println(user.getPassword());//密碼輸出為nullSystem.out.println(user.getAuthorities());//重定向到百度。這只是一個示例,具體需要看項目業務需求httpServletResponse.sendRedirect("http://www.baidu.com");} }3.2.2 修改配置項
使用successHandler()方法設置成功后交給哪個對象進行處理
// 表單認證 http.formLogin().loginProcessingUrl("/login") //當發現/login時認為是登錄,需要執行UserDetailsServiceImpl.successHandler(new MyAuthenticationSuccessHandler())//.successForwardUrl("/toMain") //此處是post請求.failureForwardUrl("/fail") //登錄失敗跳轉地址.loginPage("/login.html");4 自定義登錄失敗處理器
4.1 源碼分析
failureForwardUrl()內部調用的是failureHandler()方法
ForwardAuthenticationFailureHandler中也是一個請求轉發,并在request作用域中設置SPRING_SECURITY_LAST_EXCEPTION的key,內容為異常對象。
4.2 代碼實現
4.2.1 新建控制器
新建com.bjsxt.handler.MyForwardAuthenticationFailureHandler實現AuthenticationFailureHandler。在方法中添加重定向語句
public class MyForwardAuthenticationFailureHandler implements AuthenticationFailureHandler {@Overridepublic void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {httpServletResponse.sendRedirect("/fail.html");} }4.2.2 修改配置類
修改配置類中表單登錄部分。設置失敗時交給失敗處理器進行操作。failureForwardUrl和failureHandler不可共存。
五、 完整認證流程(包含自定義頁面和自定義登錄邏輯)
總結
以上是生活随笔為你收集整理的SpringSecurity认证的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 以物易物是什么意思 以物易物的意思
- 下一篇: SpringSecurity授权(访问控