下面是SpringSecurity自定义表单登录的实现攻略:
1. 确定用户信息来源
在进行 SpringSecurity 表单登录认证之前,我们需要确定用户信息的来源。通常,我们可以从数据库、LDAP、Active Directory 或者使用第三方的 SAML/OAuth2 身份验证服务中获取用户信息,这里我们以数据库中获取用户信息为例。
2. 用户认证流程
SpringSecurity 表单登录认证的流程如下:
- 用户访问需要进行认证的资源,如 /login 页面。
- 进入登录页面后,用户输入用户名和密码,提交表单。
- SpringSecurity 接收请求,对用户名和密码进行认证。
- 如果用户名和密码正确,SpringSecurity 为用户生成一个令牌,并把令牌返回给客户端。
- 后续的每个请求都会携带该令牌信息,SpringSecurity 通过此令牌对请求进行权限校验。
3. 实现步骤
下面是自定义表单登录的实现步骤:
3.1 导入所需依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
3.2 实现 UserDetailsSerrvice 接口
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if(user == null) {
throw new UsernameNotFoundException("用户名不存在!");
}
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
user.getAuthorities());
}
}
UserDetailsService 接口用于从数据库中获取用户信息。
3.3 实现 AuthenticationProvider 接口
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Autowired
private CustomUserDetailsService userDetailsService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = (String) authentication.getCredentials();
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if(!password.equals(userDetails.getPassword())) {
throw new BadCredentialsException("密码不正确!");
}
return new UsernamePasswordAuthenticationToken(username, password, userDetails.getAuthorities());
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
AuthenticationProvider 接口用于对用户的登陆信息进行认证。
3.4 配置 Security
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(customAuthenticationProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.successForwardUrl("/index")
.permitAll()
.and()
.logout().permitAll();
}
}
在 SecurityConfig 中,我们指定了 CustomAuthenticationProvider 来进行认证,还配置了登录页面的路径、认证成功后跳转的页面路径。
3.5 创建登录页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<form action="/login" method="post">
<label for="username">用户名:</label>
<input type="text" id="username" name="username"><br>
<label for="password">密码:</label>
<input type="password" id="password" name="password"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
4. 示例
下面提供两个示例:
4.1 基于 JPA 的用户认证
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if(user == null) {
throw new UsernameNotFoundException("用户名不存在!");
}
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
user.getAuthorities());
}
}
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Autowired
private CustomUserDetailsService userDetailsService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = (String) authentication.getCredentials();
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if(!password.equals(userDetails.getPassword())) {
throw new BadCredentialsException("密码不正确!");
}
return new UsernamePasswordAuthenticationToken(username, password, userDetails.getAuthorities());
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(customAuthenticationProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.successForwardUrl("/index")
.permitAll()
.and()
.logout().permitAll();
}
}
4.2 基于 MyBatis 的用户认证
@Repository
public interface UserMapper {
@Select("select * from user where username = #{username}")
User findByUsername(String username);
}
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userMapper.findByUsername(username);
if(user == null) {
throw new UsernameNotFoundException("用户名不存在!");
}
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
user.getAuthorities());
}
}
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Autowired
private CustomUserDetailsService userDetailsService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = (String) authentication.getCredentials();
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if(!password.equals(userDetails.getPassword())) {
throw new BadCredentialsException("密码不正确!");
}
return new UsernamePasswordAuthenticationToken(username, password, userDetails.getAuthorities());
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(customAuthenticationProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.successForwardUrl("/index")
.permitAll()
.and()
.logout().permitAll();
}
}
以上就是 SpringSecurity 自定义表单登录的实现攻略及两个示例。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringSecurity 自定义表单登录的实现 - Python技术站