Spring Security 实现多种登录方式攻略
Spring Security 作为一个强大的安全框架,支持多种登录方式,包括传统的用户名密码登录、第三方登录、手机短信验证码登录、邮件验证码登录等。本攻略将详细介绍如何使用 Spring Security 实现多种登录方式。
传统的用户名密码登录
传统的用户名密码登录是我们最常见的登录方式,主要涉及以下几个步骤:
- 配置 Spring Security 的安全配置类,并指定用户名密码登录接口的 URL。
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/")
.permitAll()
.and()
.logout()
.permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin")
.password("{noop}admin")
.roles("ADMIN");
}
}
- 在 Spring Security 的配置类中,通过
formLogin()
方法启用表单登录,并指定登录页面的 URL。
.formLogin()
.loginPage("/login")
- 实现用户认证的逻辑。这里使用的是 InMemoryAuthentication 方式。
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin")
.password("{noop}admin")
.roles("ADMIN");
}
- 实现用户授权的逻辑。
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/")
.permitAll()
.and()
.logout()
.permitAll();
}
手机短信验证码登录
手机短信验证码登录是一种比较流行的登录方式,相比传统的用户名密码登录,它更加方便快捷。手机短信验证码登录主要涉及以下几个步骤:
- 配置 Spring Security 的安全配置类,并指定手机号码登录接口的 URL。
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/sms/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/")
.permitAll()
.and()
.logout()
.permitAll()
.and()
.apply(smsAuthenticationConfig());
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin")
.password("{noop}admin")
.roles("ADMIN");
}
private SmsAuthenticationConfig smsAuthenticationConfig() {
SmsAuthenticationConfig authenticationConfig = new SmsAuthenticationConfig();
authenticationConfig.setAuthenticationManager(authenticationManagerBean());
authenticationConfig.setAuthenticationSuccessHandler(new SmsAuthenticationSuccessHandler());
authenticationConfig.setAuthenticationFailureHandler(new SmsAuthenticationFailureHandler());
return authenticationConfig;
}
}
- 在 Spring Security 的配置类中,通过
apply()
方法配置短信验证码登录,指定短信验证码登录接口的 URL、短信验证码的有效期、短信验证码的长度等信息。
.apply(smsAuthenticationConfig());
- 实现短信验证码认证的逻辑。
public class SmsCodeAuthenticationProvider implements AuthenticationProvider {
private UserDetailsService userDetailsService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
SmsCodeAuthenticationToken authenticationToken = (SmsCodeAuthenticationToken) authentication;
UserDetails user = userDetailsService.loadUserByUsername((String) authenticationToken.getPrincipal());
if (user == null) {
throw new InternalAuthenticationServiceException("无法获取用户信息");
}
SmsCodeAuthenticationToken authenticationResult = new SmsCodeAuthenticationToken(user, user.getAuthorities());
authenticationResult.setDetails(authenticationToken.getDetails());
return authenticationResult;
}
@Override
public boolean supports(Class<?> authentication) {
return SmsCodeAuthenticationToken.class.isAssignableFrom(authentication);
}
public void setUserDetailsService(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
}
- 实现短信验证码授权的逻辑。
public class SmsCodeAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
private String mobileParameter = "mobile";
private boolean postOnly = true;
public SmsCodeAuthenticationFilter() {
super(new AntPathRequestMatcher("/sms/login", "POST"));
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("认证方法不支持:" + request.getMethod());
}
String mobile = obtainMobile(request);
if (mobile == null) {
mobile = "";
}
mobile = mobile.trim();
SmsCodeAuthenticationToken authenticationToken = new SmsCodeAuthenticationToken(mobile);
setDetails(request, authenticationToken);
return this.getAuthenticationManager().authenticate(authenticationToken);
}
protected String obtainMobile(HttpServletRequest request) {
return request.getParameter(mobileParameter);
}
protected void setDetails(HttpServletRequest request, SmsCodeAuthenticationToken authenticationToken) {
authenticationToken.setDetails(authenticationDetailsSource.buildDetails(request));
}
public void setMobileParameter(String mobileParameter) {
this.mobileParameter = mobileParameter;
}
public void setPostOnly(boolean postOnly) {
this.postOnly = postOnly;
}
}
示例1:https://github.com/wangeditor/SpringSecurity/blob/main/demo-demo02/demo02-ssm/src/main/java/io/github/wangdaopeng/chapter2/controller/SmsCodeController.java
示例2:https://github.com/bfwg/springboot-jwt-starter/blob/master/src/main/java/com/bfwg/security/auth/SmsCodeAuthenticationProvider.java
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Security 实现多种登录方式(常规方式外的邮件、手机验证码登录) - Python技术站