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

001.camunda入门(springboot集成篇)

在邮递员上发布请求但不在浏览器中(代码状态:415) - Spring Boot,thymeleaf

springboot集成ES,以及应用

SpringBoot集成Kafka