SpringBoot(3)集成Spring Security 5.0.11 自定义认证逻辑
目录
Spring Security 框架默认的认证业务逻辑是不能满足我们产品或项目的需求的,这时候如果我们使用Spring Security 框架就需要自定义用户认证逻辑。
自定义认证逻辑,我们需要关心几个问题:
- 如何处理获取用户信息
- 如何处理校验用户信息
- 如何处理密码加密解密
Spring Security自定义认证逻辑
1.如何处理获取用户信息
Spring Security 提供了UserDetailsService 接口,用来处理用户信息获取,我们只要实现这个接口
,对loadUserByUsername方法进行实现,返回UserDetails 对象即可,在这个方法中,我们可以通过username字段(帐号)去数据库查找相应的用户信息。
public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
2.如何处理校验用户信息
同样用户校验信息,Spring Security 提供了UserDetails接口,Spring Security 对 UserDetails接口有默认实现User,我们直接使用它提供的即可
public interface UserDetails extends Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
/**
* 密码
*/
String getPassword();
/**
* 帐号
*/
String getUsername();
/**
* 账户是否过期
*/
boolean isAccountNonExpired();
/**
* 用户是否被锁定
*/
boolean isAccountNonLocked();
/**
* 用户是否已过期
*/
boolean isCredentialsNonExpired();
/**
* 用户是否被禁用
*/
boolean isEnabled();
}
3.如何处理密码加密解密
Spring Security 提供了 PasswordEncoder 接口,来处理密码加密和匹配问题。密码加密使我们来调用的,如果在用户注册的是有没有调用会密码匹配不上。
public interface PasswordEncoder {
/**
* 这个方法当用户注册的时候调用
*/
String encode(CharSequence rawPassword);
/**
* 这个方法是使用登录输入的密码和用户真正的使用的密码进行匹配
*/
boolean matches(CharSequence rawPassword, String encodedPassword);
}
Spring Security 自定义认证步骤
我的环境
- SpringBoot 2.0.8
- Spring Security 5.0.11
- JDK 1.8
- Eclipse 4.11.0
- Maven 3.5.4
- Windows 10
项目结构
项目pom.xml
<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>cn.com.witsystem</groupId>
<artifactId>security</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- 管理依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.spring.platform</groupId>
<artifactId>platform-bom</artifactId>
<version>Cairo-SR7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
UserDetailsServiceImpl
package cn.com.witsystem.security.custom;
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;
import lombok.extern.slf4j.Slf4j;
/**
* 处理用户信息获取
*/
@Component
@Slf4j
public class UserDetailsServiceImpl implements UserDetailsService{
@Autowired
PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
log.info(username);
//1.通过username(帐号)查找用户信息
//2.通过获取的用户信息封装实现UserDetails接口的User对象 ,封装User对象的3个参数
//passwordEncoder.encode("123456") 对密码就行加密操作
return new User(username, passwordEncoder.encode("123456"), true, true, true, true, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
}
}
SecurityConfig
package cn.com.witsystem.security.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;
import org.springframework.security.crypto.password.PasswordEncoder;
import cn.com.witsystem.security.custom.UserDetailsServiceImpl;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
UserDetailsServiceImpl detailsServiceImpl;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.authorizeRequests()
.anyRequest()
.authenticated();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(detailsServiceImpl)
.passwordEncoder(passwordEncoder());
}
}
SecurityApplication
package cn.com.witsystem.security;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class SecurityApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(SecurityApplication.class, args);
}
@GetMapping("/hello")
public String hello() {
return "hello!";
}
}
application.yml
### 服务器端口配置
server:
port: 8080
启动测试
访问 http://localhost:8080/hello