一. 底层原理

通过浏览器/外部服务传入账号密码,以及clientId以及secret申请token,TokenEndpoint 即为校验并颁发Token的方法。

org.springframework.security.oauth2.provider.endpoint.TokenEndpoint

-- postAccessToken()方法

源码如下:

@RequestMapping(value = {"/oauth/token"},method = {RequestMethod.POST})public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {if (!(principal instanceof Authentication)) {throw new InsufficientAuthenticationException("There is no client authentication. Try adding an appropriate authentication filter.");} else {String clientId = this.getClientId(principal);ClientDetails authenticatedClient = this.getClientDetailsService().loadClientByClientId(clientId);TokenRequest tokenRequest = this.getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient);if (clientId != null && !clientId.equals("") && !clientId.equals(tokenRequest.getClientId())) {throw new InvalidClientException("Given client ID does not match authenticated client");} else {if (authenticatedClient != null) {this.oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient);}if (!StringUtils.hasText(tokenRequest.getGrantType())) {throw new InvalidRequestException("Missing grant type");} else if (tokenRequest.getGrantType().equals("implicit")) {throw new InvalidGrantException("Implicit grant type not supported from token endpoint");} else {if (this.isAuthCodeRequest(parameters) && !tokenRequest.getScope().isEmpty()) {this.logger.debug("Clearing scope of incoming token request");tokenRequest.setScope(Collections.emptySet());}if (this.isRefreshTokenRequest(parameters)) {tokenRequest.setScope(OAuth2Utils.parseParameterList((String)parameters.get("scope")));}OAuth2AccessToken token = this.getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);if (token == null) {throw new UnsupportedGrantTypeException("Unsupported grant type: " + tokenRequest.getGrantType());} else {return this.getResponse(token);}}}}}

校验Token是否合法的oauth实现类源码如下:

package org.springframework.security.oauth2.provider.endpoint;import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.token.AccessTokenConverter;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;@FrameworkEndpoint
public class CheckTokenEndpoint {private ResourceServerTokenServices resourceServerTokenServices;private AccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();protected final Log logger = LogFactory.getLog(this.getClass());private WebResponseExceptionTranslator<OAuth2Exception> exceptionTranslator = new DefaultWebResponseExceptionTranslator();public CheckTokenEndpoint(ResourceServerTokenServices resourceServerTokenServices) {this.resourceServerTokenServices = resourceServerTokenServices;}public void setExceptionTranslator(WebResponseExceptionTranslator<OAuth2Exception> exceptionTranslator) {this.exceptionTranslator = exceptionTranslator;}public void setAccessTokenConverter(AccessTokenConverter accessTokenConverter) {this.accessTokenConverter = accessTokenConverter;}@RequestMapping({"/oauth/check_token"})@ResponseBodypublic Map<String, ?> checkToken(@RequestParam("token") String value) {OAuth2AccessToken token = this.resourceServerTokenServices.readAccessToken(value);if (token == null) {throw new InvalidTokenException("Token was not recognised");} else if (token.isExpired()) {throw new InvalidTokenException("Token has expired");} else {OAuth2Authentication authentication = this.resourceServerTokenServices.loadAuthentication(token.getValue());Map<String, Object> response = this.accessTokenConverter.convertAccessToken(token, authentication);response.put("active", true);return response;}}@ExceptionHandler({InvalidTokenException.class})public ResponseEntity<OAuth2Exception> handleException(Exception e) throws Exception {this.logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());InvalidTokenException e400 = new InvalidTokenException(e.getMessage()) {public int getHttpErrorCode() {return 400;}};return this.exceptionTranslator.translate(e400);}
}

/oauth/check_token就是资源服务器请求oauth2.0授权服务器进行token认证的方法。

二. 实现自定义颁发token代码

    /*** 生成 oauth2 token** @param userName 账号* @param password 密码* @param type     登录类型* @return 返回的令牌*/@Overridepublic JSONObject getToken(String userName, String password, String type, HttpHeaders headers) {// 读取 yml文件中的clientId和secretOpenOAuth2ClientDetails clientDetails = clientProperties.getOauth2().get("admin");// 调用TokenEndpoint中的postAccessToken()方法String url = WebUtils.getServerUrl(WebUtils.getHttpServletRequest()) + "/oauth/token";// 使用oauth2密码模式登录.MultiValueMap<String, Object> postParameters = new LinkedMultiValueMap<>();postParameters.add(OAUTH2_USERNAME, userName);postParameters.add(OAUTH2_PASSWORD, password);postParameters.add(OAUTH2_CLIENT_ID, clientDetails.getClientId());postParameters.add(OAUTH2_CLIENT_SECRET, clientDetails.getClientSecret());postParameters.add(OAUTH2_GRANT_TYPE, OAUTH2_PASSWORD);// 添加参数区分,第三方登录postParameters.add(OAUTH2_LOGIN_TYPE, type);// 使用客户端的请求头,发起请求headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);// 强制移除 原来的请求头,防止token失效headers.remove(HttpHeaders.AUTHORIZATION);HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(postParameters, headers);JSONObject result = restTemplate.postForObject(url, request, JSONObject.class);log.debug("getToken url:[{}]", url);return result;}

调用成功后,直接返回token,即满足自定义颁发token的需求。

OAuth2.0实现自定义颁发token相关推荐

  1. 【One by One系列】IdentityServer4(一)OAuth2.0与OpenID Connect 1.0

    在微服务场景中,身份认证通常是集中处理,这也是有别于单体应用一把梭哈的模式,其中,在微软微服务白皮书中,提供了两种身份认证模式: 网关,没错,原话是If you're using an API Gat ...

  2. Spring Security + OAuth2.0

    授权服务器 授权服务器中有4个端点.说明如下: Authorize Endpoint :授权端点,进行授权. Token Endpoint :令牌端点,经过授权拿到对应的Token. lntrospe ...

  3. OAuth2.0实现单点登录的原理

    一.什么是单点登录 单点登录,英文是 Single Sign On,缩写为 SSO.多个站点(192.168.1.20X)共用一台认证授权服务器(192.168.1.110,用户数据库和认证授权模块共 ...

  4. oauth2 增加token 返回参数_RingCentral Tech | OAuth2.0面面观

    ▲点击"RingCentral铃盛软件"并设为[星标],及时获取RingCentral的资讯 只要是接触过开放各种开放平台的开发者,对于OAuth概念肯定不陌生.但是由于OAuth ...

  5. OAuth2.0 - 自定义模式授权 - 短信验证码登录

    一.OAuth2.0 - 自定义模式授权 上篇文章我们分析了目前的情况,演示了微服务的大环境下在保证安全的情况下通过SpringGateWay实现统一的鉴权处理,但是前面的演示中,我们都是基于用户名密 ...

  6. Springboot+oauth2.0实现微信登录(oauth2.0自定义授权模式)

    1.前置准备参考 https://blog.csdn.net/qq_34190023/article/details/81133619 2.微信登录实现流程图 3.oauth自定义授权模式 上图大概描 ...

  7. oauth2.0授权协议中刷新令牌refresh token的工作原理及生命周期分析

    在学习oauth2.0协议的时候,对于刷新令牌refresh token感觉很困惑.主要是为啥需要刷新令牌,以及刷新令牌是如何工作的,技术细节是啥?比如通过refresh token可以让access ...

  8. Oauth2.0 自定义响应值以及异常处理

    自用的响应信息主体 import cn.hutool.http.ContentType; import cn.hutool.http.HttpStatus; import com.fasterxml. ...

  9. android 新浪微博Oauth2.0认证以及自定义webview认证

    首先不得不说,自己犯了一个比较窝囊的错误,不过也不能完全怪我,因为大家都知道,新浪微博Oauth2.0提供的jar包,好家伙2M多,谁看谁都不想用,才使得我去研究1.0的使用,研究好久,终于实现可用了 ...

最新文章

  1. Handler的postDelayed()关闭的方法
  2. 大数据岗位必知必会的53个Java基础
  3. 49 jQuery事件
  4. 解决 Unable to get provider
  5. python爬虫简单实例-最简单的Python爬虫案例,看得懂说明你已入门,附赠教程
  6. spring cloud架构 - HongHu common-service 项目构建过程
  7. 【Vue.js】vue用户登录功能
  8. Python 的变量作用域和 LEGB 原则
  9. unity 烘焙参数 设置_Unity通用渲染管线(URP)系列(九)——点光源和聚光灯
  10. 机器学习基石笔记5——为什么机器可以学习(1)
  11. H2介绍 – Java嵌入式数据库
  12. 小米范工具系列之一:小米范 web查找器
  13. 兄弟连php课程,LAMP兄弟连PHP课程学习笔记 第一天 PHP基本语法
  14. 网络其他计算机无法访问,win7局域网别人无法访问我的电脑是为什么 win7其他电脑无法访问我的电脑如何修复...
  15. iOS category内部实现原理
  16. 移动安全-APP安全加固
  17. 关于class not fount的错误
  18. 为什么说深度学习和机器学习截然不同?
  19. 主叫号码未显示【一分钟教你解决】
  20. R语言安装包报错:package ‘EDASeq ’ is not available for Bioconductor version ‘3.15‘

热门文章

  1. 天视通摄像头设置教程_天视通摄像头设置教程_直播教程 | 使用虎牙伴侣背景消除,来点新鲜的直播玩法!......
  2. 计算机与应用数学专业就业方向,2020数学与应用数学专业就业前景和就业方向分析...
  3. 百读不厌《破窑赋》!真正的千古奇文!
  4. 我涉及的数据可视化的实现技术和工具
  5. GC日志的查看(日志意思)
  6. [RK3288][Android6.0] 调试笔记 --- apk安装添加黑名单
  7. ps制作的html手机怎么使用,ps制作手机的教程
  8. Java Swing中JFreeChart构建双纵轴(双Y轴)图表的使用纪要
  9. krpano场景拖动时拖动惯性消失的问题
  10. TM4C123系列ARM单片机开发入门介绍