OAuth2.0 - 自定义模式授权 - 短信验证码登录
一、OAuth2.0 - 自定义模式授权
上篇文章我们分析了目前的情况,演示了微服务的大环境下在保证安全的情况下通过SpringGateWay
实现统一的鉴权处理,但是前面的演示中,我们都是基于用户名密码的方式,但是现在已经普及短信验证码登录、微信登录、QQ登录等这些第三方的登录方式,这些方式显然不在Oauth2.0提供的四种授权模式下,因此我们如果要实现第三方的登录需要自定义一个授权模式,下面我们就以短信验证码登录为例进行实现。
下面是上篇文章的地址:
https://blog.csdn.net/qq_43692950/article/details/122566821
二、短信验证码登录
SpringOauth2.0
虽说只有四种授权模式,但是他提供了非常高的扩展性,我们可以很方便的进行授权模式的扩展,而无需大量的改动,在SpringOauth2.0
中扩展授权模式,只需继承AbstractTokenGranter
类,并在构造方法中super
父类时,指定自己的授权标识,当用户认证传入grant_type
为该标识,则会触发该生成器的getOAuth2Authentication
方法,我们可以在这里获取客户端传入的参数,比如手机号和验证码,然后我们再和预先的验证码对比,如果OK,可以根据手机号获取用户的信息组成UsernamePasswordAuthenticationToken
对象再交给Oauth2
即可:
下面编写一个SmsCodeTokenGranter
这里只是演示功能,直接将用户和验证码写死了:
public class SmsCodeTokenGranter extends AbstractTokenGranter {private static final String SMS_GRANT_TYPE = "sms_code";private UserService userService;public SmsCodeTokenGranter(AuthorizationServerTokenServices tokenServices,ClientDetailsService clientDetailsService,OAuth2RequestFactory requestFactory,UserService userService) {super(tokenServices, clientDetailsService, requestFactory, SMS_GRANT_TYPE);this.userService = userService;}@Overrideprotected OAuth2Authentication getOAuth2Authentication(ClientDetails client,TokenRequest tokenRequest) {Map<String, String> parameters = new LinkedHashMap<String, String>(tokenRequest.getRequestParameters());System.out.println(parameters.toString());// 客户端提交的手机号码String phoneNumber = parameters.get("phone");if (StringUtils.isBlank(phoneNumber)) {throw new AccessDeniedException("get phone is null !");}// 客户端提交的验证码String smsCode = parameters.get("code");if (!smsCode.equals("9876")) {throw new AccessDeniedException("code err!");}UserDetails user = userService.loadUserByUsername("admin");AbstractAuthenticationToken userAuth = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());userAuth.setDetails(parameters);OAuth2Request oAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);return new OAuth2Authentication(oAuth2Request, userAuth);}
}
下面还需修改AuthorizationServer
将上面的生成器配制进AuthorizationServerEndpointsConfigurer
中:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {@Autowiredprivate TokenStore tokenStore;@Autowired@Qualifier("jdbcClientDetailsService")private ClientDetailsService clientDetailsService;@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate AuthorizationCodeServices authorizationCodeServices;@Autowiredprivate JwtAccessTokenConverter accessTokenConverter;@AutowiredUserService userService;@AutowiredPasswordEncoder passwordEncoder;@Bean("jdbcClientDetailsService")public ClientDetailsService clientDetailsService(DataSource dataSource) {JdbcClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource);clientDetailsService.setPasswordEncoder(passwordEncoder);return clientDetailsService;}@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.withClientDetails(clientDetailsService);}@Beanpublic AuthorizationCodeServices authorizationCodeServices(DataSource dataSource) {return new JdbcAuthorizationCodeServices(dataSource);//设置授权码模式的授权码如何存取}@Beanpublic AuthorizationServerTokenServices tokenService() {DefaultTokenServices service = new DefaultTokenServices();service.setClientDetailsService(clientDetailsService);service.setSupportRefreshToken(true);service.setTokenStore(tokenStore);//令牌增强TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();List<TokenEnhancer> tokenEnhancers = new ArrayList<>();//内容增强tokenEnhancers.add(tokenEnhancer());tokenEnhancers.add(accessTokenConverter);tokenEnhancerChain.setTokenEnhancers(tokenEnhancers);service.setTokenEnhancer(tokenEnhancerChain);service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天return service;}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) {endpoints.authenticationManager(authenticationManager)//认证管理器.authorizationCodeServices(authorizationCodeServices)//授权码服务.tokenGranter(tokenGranter(endpoints)).tokenServices(tokenService())//令牌管理服务.allowedTokenEndpointRequestMethods(HttpMethod.POST);}@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security.tokenKeyAccess("permitAll()") //oauth/token_key是公开.checkTokenAccess("permitAll()") //oauth/check_token公开.allowFormAuthenticationForClients(); //表单认证(申请令牌)}/*** JWT内容增强*/@Beanpublic TokenEnhancer tokenEnhancer() {return (accessToken, authentication) -> {Map<String, Object> additionalInfo = new HashMap<>();additionalInfo.put("userid", -1);Authentication auth = authentication.getUserAuthentication();if (auth != null) {UserEntity user = (UserEntity) auth.getPrincipal();additionalInfo.put("userid", user.getId());}else {String clientId = authentication.getOAuth2Request().getClientId();String grantType = authentication.getOAuth2Request().getRequestParameters().get("grant_type");if (Objects.equals(clientId, "c1") && Objects.equals(grantType, "client_credentials")) {additionalInfo.put("userid", "root");}}((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);return accessToken;};}/*** 添加自定义授权类型** @return List<TokenGranter>*/private TokenGranter tokenGranter(AuthorizationServerEndpointsConfigurer endpoints) {// endpoints.getTokenGranter() 获取SpringSecurity OAuth2.0 现有的授权类型List<TokenGranter> granters = new ArrayList<TokenGranter>(Collections.singletonList(endpoints.getTokenGranter()));// 构建短信验证授权类型SmsCodeTokenGranter smsCodeTokenGranter = new SmsCodeTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(),endpoints.getOAuth2RequestFactory(),userService);// 向集合中添加短信授权类型granters.add(smsCodeTokenGranter);// 返回所有类型return new CompositeTokenGranter(granters);}}
三、测试
使用PostMan
发送POST
请求:
http://localhost:8020/oauth/token?client_id=c1&client_secret=secret&grant_type=sms_code&phone=110&code=9562
注意:grant_type
要传sms_code
可以看到返回的是Unauthorized grant type: sms_code
未授权的类型,这个是因为c1这个客户端没有sms_code
认证类型,给c1添加上sms_code
类型:
下面重新测试:
已经有我我们写的返回了,下面输入正确的验证码:
http://localhost:8020/oauth/token?client_id=c1&client_secret=secret&grant_type=sms_code&phone=110&code=9876
已经成功获取到令牌。
喜欢的小伙伴可以关注我的个人微信公众号,获取更多学习资料!
OAuth2.0 - 自定义模式授权 - 短信验证码登录相关推荐
- SpringBoot OAuth2.0 使用短信验证码登录授权
SpringBoot OAuth2.0 使用短信验证码登录授权 实现步骤: 自定义授权器,继承 AbstractTokenGranter 类: 重写 getOAuth2Authentication 函 ...
- Spring Security OAuth2 优雅的集成短信验证码登录以及第三方登录
基于SpringCloud做微服务架构分布式系统时,OAuth2.0作为认证的业内标准,Spring Security OAuth2也提供了全套的解决方案来支持在Spring Cloud/Spring ...
- cas5.3.9自定义手机短信验证码登录
cas自定义多种登录方式 cas添加手机短信验证码登录 cas添加手机短信验证码登录 全部基于SpringBoot,以及SpringWebflow开发,请在有此基础再进行学习! 添加Maven依赖 & ...
- 短信验证码登录,以及第三方登录
短信验证码登录 首先去阿里云服务器开通短信服务功能,进入短信服务界面 点击国内消息,申请一个签名和模板 申请一个AccessKey,并且将短信服务的权限加入其中 加入相关的依赖 <depende ...
- 5.Spring Security 短信验证码登录
Spring Security 短信验证码登录 在 Spring Security 添加图形验证码一节中,我们已经实现了基于 Spring Boot + Spring Security 的账号密码登录 ...
- 手机短信验证码登录功能的开发实录(机器识别码、短信限流、错误提示、发送验证码倒计时60秒)
短信验证码登录功能 项目分析 核心代码 1.外部js库调用 2.HTML容器构建 3.javaScript业务逻辑验证 4.后端验证逻辑 总结 短信验证码是通过发送验证码到手机的一种有效的验证码系统, ...
- SpringSecurity短信验证码登录
短信验证码登录 时下另一种非常常见的网站登录方式为手机短信验证码登录,但Spring Security默认只提供了账号密码的登录认证逻辑,所以要实现手机短信验证码登录认证功能,我们需要模仿Spring ...
- Redis(2)短信验证码登录
Redis实现短信验证码登录 登录流程 1.发送验证码: 2.短信验证码登录,注册 3.校验登录状态 解决状态登录刷新问题 redis指令参考:https://blog.csdn.net/weixin ...
- Spring Security 短信验证码登录(5)
在Spring Security添加图形验证码中,我们已经实现了基于Spring Boot + Spring Security的账号密码登录,并集成了图形验证码功能.时下另一种非常常见的网站登录方式为 ...
最新文章
- pycharm 无法导包、无法导入模块(模块名不能含有连接符“-”)
- Macbook m1 install Homebrew
- POJ 3750 小孩报数问题
- attribute java c_属性别名(Attribute Aliasing)
- linux添加文件后无法启动,linux安装后grub无法启动
- 修改Tomcat端口号
- Run-time error “70“:Permission denied
- 不同php文件,不同文件构建PHP程序的正确方式
- 计算机二级 java和web_2016计算机二级web程序设计判断题及答案
- 2019.2.18接口2
- Matlab R2016a安装教程
- ECRS分析原则(转载)
- 基于人工萤火虫优化(GSO)算法的函数寻优算法
- 发送邮件被对方服务器退回_国内邮件群发
- Unity图片闪烁效果
- 【单片机】温度感应报警装置的设计与制作(说明书)
- sqlserver进阶必会基础入门不止select into from 插入数据必知
- cartographer源码解析(二)node_main.cc文件详解
- 宣城市高新技术企业认定补贴政策 申报流程整理分析
- mysql.data.dll 位置_MySql.Data.dll,下载,简介,描述,修复,等相关问题一站搞定_DLL之家...