SpringBoot集成SpringSecurity(十七手机号登录)
Posted 伍妖捌
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot集成SpringSecurity(十七手机号登录)相关的知识,希望对你有一定的参考价值。
前言
SpringSecurity默认不支持短信验证码登录,而现在手机验证码登录随处可见,下面对SpringSecurity进行集成手机短信登录。
实现
public class MobileAuthenticationToken extends AbstractAuthenticationToken {
private static final long serialVersionUID = 540L;
private final Object principal; // 认证前是手机号,最终保存用户信息
public MobileAuthenticationToken(Object principal) {
super(null);
this.principal = principal;
this.setAuthenticated(false);
}
public MobileAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
super.setAuthenticated(true);
}
public Object getCredentials() {
return null;
}
public Object getPrincipal() {
return this.principal;
}
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
Assert.isTrue(!isAuthenticated, "Cannot set this token to trusted - use constructor which takes a " +
"GrantedAuthority list instead");
super.setAuthenticated(false);
}
public void eraseCredentials() {
super.eraseCredentials();
}
}
public class MobileAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
private String mobileParameter = "mobile";
private boolean postOnly = true;
public MobileAuthenticationFilter() {
super(new AntPathRequestMatcher("/login/mobile", "POST"));
}
public MobileAuthenticationFilter(AuthenticationManager authenticationManager) {
super(new AntPathRequestMatcher("/login/mobile", "POST"), authenticationManager);
}
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws
AuthenticationException {
if (this.postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
} else {
String mobile = this.obtainMobile(request);
mobile = mobile != null ? mobile : "";
mobile = mobile.trim();
MobileAuthenticationToken authRequest = new MobileAuthenticationToken(mobile);
this.setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
}
private String obtainMobile(HttpServletRequest request) {
return request.getParameter(this.mobileParameter);
}
/**
* 将sessionId和hostname添加到MobileAuthenticationToken
*
* @param request request
* @param authRequest authRequest
*/
private void setDetails(HttpServletRequest request, MobileAuthenticationToken authRequest) {
authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
}
public void setPostOnly(boolean postOnly) {
this.postOnly = postOnly;
}
public String getMobileParameter() {
return mobileParameter;
}
public void setMobileParameter(String mobileParameter) {
this.mobileParameter = mobileParameter;
}
}
public class MobileAuthenticationProvider implements AuthenticationProvider {
private UserDetailsService userDetailsService;
public void setUserDetailsService(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
MobileAuthenticationToken mobileAuthenticationToken = (MobileAuthenticationToken) authentication;
String mobile = (String) mobileAuthenticationToken.getPrincipal();
UserDetails userDetails = userDetailsService.loadUserByUsername(mobile);
MobileAuthenticationToken authenticationToken = new MobileAuthenticationToken(userDetails, userDetails
.getAuthorities());
authenticationToken.setDetails(mobileAuthenticationToken.getDetails());
return authenticationToken;
}
@Override
public boolean supports(Class<?> aClass) {
return MobileAuthenticationToken.class.isAssignableFrom(aClass);
}
}
@Service
public class MobileUserDetails implements UserDetailsService {
@Autowired
private SysUserService sysUserService;
@Override
public UserDetails loadUserByUsername(String mobile) throws UsernameNotFoundException {
SysUser sysUser = sysUserService.findUserMenuByMobile(mobile);
if (sysUser == null) {
throw new UsernameNotFoundException("用户名或密码错误");
}
return sysUser;
}
}
@Component
public class MobileConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
@Autowired
LoginSuccessHandler loginSuccessHandler;
@Autowired
LoginFailureHandler loginFailureHandler;
@Autowired
MobileUserDetails mobileUserDetails ;
@Override
public void configure(HttpSecurity http) {
MobileAuthenticationFilter mobileAuthenticationFilter = new MobileAuthenticationFilter();
mobileAuthenticationFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));
mobileAuthenticationFilter.setAuthenticationSuccessHandler(loginSuccessHandler);
mobileAuthenticationFilter.setAuthenticationFailureHandler(loginFailureHandler);
mobileAuthenticationFilter.setRememberMeServices(http.getSharedObject(RememberMeServices.class));
SessionAuthenticationStrategy sessionStrategy = http.getSharedObject(SessionAuthenticationStrategy.class);
mobileAuthenticationFilter.setSessionAuthenticationStrategy(sessionStrategy);
MobileAuthenticationProvider mobileAuthenticationProvider = new MobileAuthenticationProvider();
mobileAuthenticationProvider.setUserDetailsService(mobileUserDetails);
http.authenticationProvider(mobileAuthenticationProvider);
http.addFilterBefore(mobileAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
}
@Autowired
private MobileConfig mobileConfig;
http.apply(mobileConfig);
public interface SmsService {
/**
* 发送短信验证码
*
* @param mobile 手机号
* @param content 发送内容
* @return 成功/失败
*/
boolean sendSms(String mobile, String content);
}
@Service
public class Sms implements SmsService {
@Override
public boolean sendSms(String mobile, String content) {
String pattern = String.format("IT独狼,验证码为%s,请妥善保管,不要泄露!", content);
log.info("向手机号为:{},成功发送了一条验证码:{}", mobile, content);
return true;
}
}
/**
* 生成手机验证码
*
* @param request request
*/
@GetMapping("code/sms")
public Result smsCode(HttpServletRequest request, @RequestParam String mobile) {
String code = RandomStringUtils.randomNumeric(4);
request.getSession().setAttribute(Constant.SMS_CODE, code);
smsService.sendSms(mobile, code);
return Result.ok().message("短信发送成功");
}
以上是关于SpringBoot集成SpringSecurity(十七手机号登录)的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot项目启动后访问任意接口都会跳转到一个莫名其妙的login登录页面
SpringSecurity解决跨域问题,在SpringBoot整合SprinSecurity中如何用前后端分离Ajax登录,Ajax登录返回状态200还是近error