在 Spring Boot 项目中整合 Spring Security 并自定义登录接口可以通过以下步骤完成。这里是一个简化的指南和代码示例。
1. 添加依赖
首先,你需要在 pom.xml
文件中添加必要的依赖。以下是 Spring Boot 和 Spring Security 的常见依赖:
<dependencies>
<!-- Spring Boot Starter Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Starter Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Spring Boot Starter Data JPA (if you are using JPA) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- H2 Database (for testing, replace with your database dependency) -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Lombok (optional, for simplifying code) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
</dependencies>
2. 创建自定义用户详细信息
创建一个实现 UserDetails
接口的类,以便能够在认证过程中使用自定义的用户信息。
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
public class CustomUserDetails implements UserDetails {
private String username;
private String password;
private Collection<? extends GrantedAuthority> authorities;
public CustomUserDetails(String username, String password, Collection<? extends GrantedAuthority> authorities) {
this.username = username;
this.password = password;
this.authorities = authorities;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
3. 创建用户服务类
实现 UserDetailsService
接口来加载用户的详细信息。
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 这里你可以通过从数据库获取用户信息来构造 CustomUserDetails 对象
// 示例中使用硬编码的用户数据
if ("user".equals(username)) {
return new CustomUserDetails(username, "password", List.of(() -> "ROLE_USER"));
} else {
throw new UsernameNotFoundException("User not found");
}
}
}
4. 配置 Spring Security
创建一个 SecurityConfig
类来配置 Spring Security,包括自定义登录接口。
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.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService userDetailsService;
@Bean
public CustomAuthenticationFilter customAuthenticationFilter() throws Exception {
CustomAuthenticationFilter filter = new CustomAuthenticationFilter();
filter.setAuthenticationManager(authenticationManagerBean());
return filter;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(customAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
5. 自定义认证过滤器
创建一个自定义的认证过滤器,处理登录请求并进行身份验证。
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
// 解析请求中的 JSON 数据
LoginRequest loginRequest = new ObjectMapper().readValue(request.getInputStream(), LoginRequest.class);
return getAuthenticationManager().authenticate(
new UsernamePasswordAuthenticationToken(
loginRequest.getUsername(),
loginRequest.getPassword()
)
);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
6. 创建登录请求 DTO
创建一个用于接收登录请求数据的 DTO 类。
public class LoginRequest {
private String username;
private String password;
// Getters and setters
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
7. 测试
启动你的 Spring Boot 应用程序,并发送一个 POST 请求到 /login
接口,包含 JSON 格式的用户名和密码,例如:
{
"username": "user",
"password": "password"
}
总结
以上是一个基本的 Spring Boot 与 Spring Security 整合的自定义登录接口的实现示例。根据你的需求,你可能需要调整和扩展这些代码,例如增加用户验证逻辑、处理异常、配置 JWT 等。这个示例只是一个起点,希望能帮助你理解整体的整合过程。