Spring Security Oauth2.0 实现短信验证码登录示例
程序员文章站
2023-12-13 19:36:10
本文介绍了spring security oauth2.0 实现短信验证码登录示例,分享给大家,具体如下:
定义手机号登录令牌
/**
* @autho...
本文介绍了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 illegalargumentexception( "cannot set this token to trusted - use constructor which takes a grantedauthority list instead"); } super.setauthenticated(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; } 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<defaultsecurityfilterchain, httpsecurity> { @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="
源码
请参考
基于spring cloud、spring security oauth2.0开发企业级认证与授权,提供常见服务监控、链路追踪、日志分析、缓存管理、任务调度等实现
整个逻辑是参考spring security 自身的 usernamepassword 登录模式实现,可以参考其源码。
验证码的发放、校验逻辑比较简单,方法后通过全局fiter 判断请求中code 是否和 手机号匹配集合,重点逻辑是令牌的参数
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
Spring Security Oauth2.0 实现短信验证码登录示例
-
Spring Security OAuth2集成短信验证码登录以及第三方登录
-
Spring Security OAuth2集成短信验证码登录以及第三方登录
-
Springboot+Spring Security实现前后端分离登录认证及权限控制的示例代码
-
SpringBoot + Spring Security 学习笔记(五)实现短信验证码+登录功能
-
Spring Security 自定义短信登录认证的实现
-
node中短信api实现验证码登录的示例代码
-
Spring Security短信验证码实现详解
-
SpringBoot + Spring Security 学习笔记(五)实现短信验证码+登录功能
-
Spring Security短信验证码实现详解