Spring Security Oauth2.0 实现短信验证码登录示例

网友投稿 598 2023-02-27


Spring Security Oauth2.0 实现短信验证码登录示例

本文介绍了Spring Security Oauth2.0 实现短信验证码登录示例,分享给大家,具体如下:

定义手机号登录令牌

/**

* @author lengleng

* @date 2018/1/9

* 手机号登录令牌

*/

public class MobileAuthenticationToken extends AbstractAuthenticationToken {

private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;

private final Object principal;

public MobileAuthenticationToken(String mobile) {

super(null);

this.principal = mobile;

setAuthenticated(false);

}

public MobileAuthenticationToken(Object principal,

Collection extends GrantedAuthority> authorities) {

super(authorities);

this.principal = principal;

super.setAuthenticated(true);

}

public Object getPrincipal() {

return this.principal;

}

@Override

public Object getCredentials() {

return null;

}

public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {

if (isAuthenticated) {

throw new IllegalArgumKFmpVHzMZentException(

"Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");

}

super.setAuthenticKFmpVHzMZated(false);

}

@Override

public void eraseCredentials() {

super.eraseCredentials();

}

}

手机号登录校验逻辑

/**

* @author lengleng

* @date 2018/1/9

* 手机号登录校验逻辑

*/

public class MobileAuthenticationProvider implements AuthenticationProvider {

private UserService userService;

@Override

public Authentication authenticate(Authentication authentication) throws AuthenticationException {

MobileAuthenticationToken mobileAuthenticationToken = (MobileAuthenticationToken) authentication;

UserVo userVo = userService.findUserByMobile((String) mobileAuthenticationToken.getPrincipal());

UserDetailsImpl userDetails = buildUserDeatils(userVo);

if (userDetails == null) {

throw new InternalAuthenticationServiceException("手机号不存在:" + mobileAuthenticationToken.getPrincipal());

}

MobileAuthenticationToken authenticationToken = new MobileAuthenticationToken(userDetails, userDetails.getAuthorities());

authenticationToken.setDetails(mobileAuthenticationToken.getDetails());

return authenticationToken;

http:// }

private UserDetailsImpl buildUserDeatils(UserVo userVo) {

return new UserDetailsImpl(userVo);

}

@Override

public boolean supports(Class> authentication) {

return MobileAuthenticationToken.class.isAssignableFrom(authentication);

}

public UserService getUserService() {

return userService;

}

public void setUserService(UserService userService) {

this.userService = userService;

}

}

登录过程filter处理

/**

* @author lengleng

* @date 2018/1/9

* 手机号登录验证filter

*/

public class MobileAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

public static final String SPRING_SECURITY_FORM_MOBILE_KEY = "mobile";

private String mobileParameter = SPRING_SECURITY_FORM_MOBILE_KEY;

private boolean postOnly = true;

public MobileAuthenticationFilter() {

super(new AntPathRequestMatcher(SecurityConstants.MOBILE_TOKEN_URL, "POST"));

}

public Authentication attemptAuthentication(HttpServletRequest request,

HttpServletResponse response) throws AuthenticationException {

if (postOnly && !request.getMethod().equals(HttpMethod.POST.name())) {

throw new AuthenticationServiceException(

"Authentication method not supported: " + request.getMethod());

}

String mobile = obtainMobile(request);

if (mobile == null) {

mobile = "";

}

mobile = mobile.trim();

MobileAuthenticationToken mobileAuthenticationToken = new MobileAuthenticationToken(mobile);

setDetails(request, mobileAuthenticationToken);

return this.getAuthenticationManager().authenticate(mobileAuthenticationToken);

}

protected String obtainMobile(HttpServletRequest request) {

return request.getParameter(mobileParameter);

}

protected void setDetails(HttpServletRequest request,

MobileAuthenticationToken authRequest) {

authRequest.setDetails(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 boolean isPostOnly() {

return postOnly;

}

}

生产token 位置

/**

* @author lengleng

* @date 2018/1/8

* 手机号登录成功,返回oauth token

*/

@Component

public class MobileLoginSuccessHandler implements org.springframework.security.web.authentication.AuthenticationSuccessHandler {

private Logger logger = LoggerFactory.getLogger(getClass());

@Autowired

private ObjectMapper objectMapper;

@Autowired

private ClientDetailsService clientDetailsService;

@Autowired

private AuthorizationServerTokenServices authorizationServerTokenServices;

@Override

public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {

String header = request.getHeader("Authorization");

if (header == null || !header.startsWith("Basic ")) {

throw new UnapprovedClientAuthenticationException("请求头中client信息为空");

}

try {

String[] tokens = extractAndDecodeHeader(header);

assert tokens.length == 2;

String clientId = tokens[0];

String clientSecret = tokens[1];

jsONObject params = new JSONObject();

params.put("clientId", clientId);

params.put("clientSecret", clientSecret);

params.put("authentication", authentication);

ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);

TokenRequest tokenRequest = new TokenRequest(MapUtil.newHashMap(), clientId, clientDetails.getScope(), "mobile");

OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);

OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);

OAuth2AccessToken oAuth2AccessToken = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);

logger.info("获取token 成功:{}", oAuth2AccessToken.getValue());

response.setCharacterEncoding(CommonConstant.UTF8);

response.setContentType(CommonConstant.CONTENT_TYPE);

PrintWriter printWriter = response.getWriter();

printWriter.append(objectMapper.writeValueAsString(oAuth2AccessToken));

} catch (IOException e) {

throw new BadCredentialsException(

"Failed to decode basic authentication token");

}

}

/**

* Decodes the header into a username and password.

*

* @throws BadCredentialsException if the Basic header is not present or is not valid

* Base64

*/

private String[] extractAndDecodeHeader(String header)

throws IOException {

byte[] base64Token = header.substring(6).getBytes("UTF-8");

byte[] decoded;

try {

decoded = Base64.decode(base64Token);

} catch (IllegalArgumentException e) {

throw new BadCredentialsException(

"Failed to decode basic authentication token");

}

String token = new String(decoded, CommonConstant.UTF8);

int delim = token.indexOf(":");

if (delim == -1) {

throw new BadCredentialsException("Invalid basic authentication token");

}

return new String[]{token.substring(0, delim), token.substring(delim + 1)};

}

}

配置以上自定义

//**

* @author lengleng

* @date 2018/1/9

* 手机号登录配置入口

*/

@Component

public class MobileSecurityConfigurer extends SecurityConfigurerAdapter {

@Autowired

private MobileLoginSuccessHandler mobileLoginSuccessHandler;

@Autowired

private UserService userService;

@Override

public void configure(HttpSecurity http) throws Exception {

MobileAuthenticationFilter mobileAuthenticationFilter = new MobileAuthenticationFilter();

mobileAuthenticationFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));

mobileAuthenticationFilter.setAuthenticationSuccessHandler(mobileLoginSuccessHandler);

MobileAuthenticationProvider mobileAuthenticationProvider = new MobileAuthenticationProvider();

mobileAuthenticationProvider.setUserService(userService);

http.authenticationProvider(mobileAuthenticationProvider)

.addFilterAfter(mobileAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

}

}

在spring security 配置 上边定一个的那个聚合配置

/**

* @author lengleng

* @date 2018年01月09日14:01:25

* 认证服务器开放接口配置

*/

@Configuration

@EnableResourceServer

public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

@Autowired

private FilterUrlsPropertiesConifg filterUrlsPropertiesConifg;

@Autowired

private MobileSecurityConfigurer mobileSecurityConfigurer;

@Override

public void configure(HttpSecurity http) throws Exception {

registry

.antMatchers("/mobile/token").permissionAll()

.anyRequest().authenticated()

.and()

.csrf().disable();

http.apply(mobileSecurityConfigurer);

}

}

使用

复制代码 代码如下:

curl -H "Authorization:Basic cGlnOnBpZw==" -d "grant_type=mobile&scope=server&mobile=17034642119&code=" http://localhost:9999/auth/mobile/token

源码

请参考gitee.com/log4j/

基于Spring Cloud、Spring Security Oauth2.0开发企业级认证与授权,提供常见服务监控、链路追踪、日志分析、缓存管理、任务调度等实现

整个逻辑是参考spring security 自身的 usernamepassword 登录模式实现,可以参考其源码。

验证码的发放、校验逻辑比较简单,方法后通过全局fiter 判断请求中code 是否和 手机号匹配集合,重点逻辑是令牌的参数


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Vuex 进阶之模块化组织详解
下一篇:详解使用Spring Security OAuth 实现OAuth 2.0 授权
相关文章

 发表评论

暂时没有评论,来抢沙发吧~