[Spring Security] Spring Security基於表單的登入認證
阿新 • • 發佈:2019-02-06
1.基本原理
SpringSecurity 最核心的部分是由一系列的過濾器組成的過濾器鏈,每個過濾器都負責處理一種認證方式,請求經過任何一個過濾器過濾後,都會在請求上做一個標記,來記錄認證是否成功,最後由FilterSecurityInterceptor根據我們配置的許可權來決定是否能通過認證,從而訪問我們的服務。今天我們主要使用的是用來處理表單登入的UsernamePasswordAuthenticationFilter。
2.實現:
程式碼結構:
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"> <modelVersion>4.0.0</modelVersion> <groupId>com.springsecurity.login</groupId> <artifactId>security-login</artifactId> <version>1.0-SNAPSHOT</version> <dependencyManagement><!--用來管理依賴版本--> <dependencies> <dependency> <groupId>io.spring.platform</groupId> <artifactId>platform-bom</artifactId> <version>Brussels-SR4</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-taglibs</artifactId> </dependency> </dependencies> </project>
loginPage.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>security login</title> </head> <body> <h3>登入</h3> <form action="/authentication/form" method="post"> <table> <tr> <td>使用者名稱:</td> <td><input type="text" name="username"></td> </tr> <tr> <td>密碼:</td> <td><input type="password" name="password"></td> </tr> <tr> <td colspan="2"><button type="submit">登入</button></td> </tr> </table> </form> </body> </html>
SecurityConfig:
package com.security.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; /** * @author ShotMoon */ @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } /** * @description : * @param : [http] * @return : void */ @Override protected void configure(HttpSecurity http) throws Exception { http.formLogin() .loginPage("/loginPage.html")//指定自定義登入頁面,不指定則使用預設配置的 .loginProcessingUrl("/authentication/form")//登入請求url-form表單的action .and() .authorizeRequests()/配置請求需要認證 .antMatchers( "/loginPage.html" ).permitAll()//指定不需認證的路徑,防止出現登入頁需要認證而發生死迴圈的狀況 .anyRequest()//所有請求都需認證 .authenticated() .and() .csrf().disable(); } }
UserController:
package com.security.controller; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.GetMapping; /** * @author ShotMoon */ @RestController public class UserController { /** * @description : * @param : [] * @return : java.util.List<com.shotmoon.dto.User> * @date : 2018/5/10 18:28 */ @GetMapping("/user") public String enter(){ String success = "登入成功"; return success; } }
MyUserDetailService:
package com.security; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Component; /** * @author ShotMoon */ @Component public class MyUserDetailService implements UserDetailsService{ private Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private PasswordEncoder passwordEncoder; /** * @description : * @param : [username] * @return : org.springframework.security.core.userdetails.UserDetails * @date : 2018/5/12 23:11 */ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { logger.info("使用者名稱:" + username); //根據使用者名稱到資料庫查詢使用者的資訊,這裡我使用mock資料,大家可以根據自己的資料庫來 String password = passwordEncoder.encode("123"); logger.info("資料庫加密密碼:" + password); return new User(username, password, true,true,true,true, //boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked可根據業務進行配置 AuthorityUtils.commaSeparatedStringToAuthorityList("admin")); } }
其中PassWordEncoder用來處理使用者的加密及匹配,看一下原始碼:
這樣,基於SpringSecurity實現加密的表單登入就完成了。package org.springframework.security.crypto.password; public interface PasswordEncoder { String encode(CharSequence var1);//加密輸入的密碼 boolean matches(CharSequence var1, String var2);//驗證加密的密碼與資料庫資料是否匹配 }