我扒了半天源码,终于找到了Oauth2自定义处理结果的最佳方案!

论坛 期权论坛     
选择匿名的用户   2021-5-26 13:29   2941   0
<p>原创 梦想de星空 <a id="js_name">macrozheng</a> <em id="publish_time">今天</em></p>
<p>来自专辑</p>
<p>Spring Cloud学习教程</p>
<blockquote>
<p>在<a href="https://mp.weixin.qq.com/s?__biz&#61;MzU1Nzg4NjgyMw&#61;&#61;&amp;mid&#61;2247485818&amp;idx&#61;1&amp;sn&#61;042320bf303b75835bbc5f59607fd2e5&amp;scene&#61;21#wechat_redirect">《微服务权限终极解决方案,Spring Cloud Gateway &#43; Oauth2 实现统一认证和鉴权!》</a>一文中我们介绍了Oauth2在微服务中的使用,但是我们没有自定义Oauth2默认的处理结果。有时候我们真的很希望Oauth2中的认证授权能返回我们指定格式的结果,比如登录认证的结果、网关鉴权不通过的结果等等。本文将详细介绍Oauth2中自定义处理结果的方案,希望对大家有所帮助!</p>
</blockquote>
<h2>解决什么问题</h2>
<blockquote>
<p>自定义Oauth2处理结果,主要是为了统一接口返回信息的格式,从下面几个方面着手。</p>
</blockquote>
<ul><li> <p>自定义Oauth2登录认证成功和失败的返回结果;</p> </li><li> <p>JWT令牌过期或者签名不正确,网关认证失败的返回结果;</p> </li><li> <p>携带过期或者签名不正确的JWT令牌访问白名单接口,网关直接认证失败。</p> </li></ul>
<h2>自定义登录认证结果</h2>
<h3>认证成功返回结果</h3>
<ul><li> <p>我们先来看看默认的返回结果,访问Oauth2登录认证接口:http://localhost:9201/auth/oauth/token</p> </li></ul>
<p><img alt="" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-77325cc2128ca828b27567cd25046bf5"></p>
<ul><li> <p>我们之前使用的都是统一的通用返回结果<code>CommonResult</code>,Oauth2的这个结果显然不符合,需要统一下,通用返回结果格式如下;</p> </li></ul>
<pre class="blockcode"><code>/**
* 通用返回对象
* Created by macro on 2019/4/19.
*/
public class CommonResult&lt;T&gt; {
    private long code;
    private String message;
    private T data;
}
</code></pre>
<ul><li> <p>其实我们只要找到一个关键类就可以自定义Oauth2的登录认证接口了,它就是<code>org.springframework.security.oauth2.provider.endpoint.TokenEndpoint</code>,其中定义了我们非常熟悉的登录认证接口,我们只要自己重写登录认证接口,直接调用默认的实现逻辑,然后把默认返回的结果处理下即可,下面是默认的实现逻辑;</p> </li></ul>
<pre class="blockcode"><code>&#64;FrameworkEndpoint
public class TokenEndpoint extends AbstractEndpoint {

&#64;RequestMapping(value &#61; &#34;/oauth/token&#34;, method&#61;RequestMethod.POST)
public ResponseEntity&lt;OAuth2AccessToken&gt; postAccessToken(Principal principal, &#64;RequestParam
Map&lt;String, String&gt; parameters) throws HttpRequestMethodNotSupportedException {

  if (!(principal instanceof Authentication)) {
   throw new InsufficientAuthenticationException(
     &#34;There is no client authentication. Try adding an appropriate authentication filter.&#34;);
  }

  String clientId &#61; getClientId(principal);
  ClientDetails authenticatedClient &#61; getClientDetailsService().loadClientByClientId(clientId);

  TokenRequest tokenRequest &#61; getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient);

  if (clientId !&#61; null &amp;&amp; !clientId.equals(&#34;&#34;)) {
   // Only validate the client details if a client authenticated during this
   // request.
   if (!clientId.equals(tokenRequest.getClientId())) {
    // double check to make sure that the client ID in the token request is the same as that in the
    // authenticated client
    throw new InvalidClientException(&#34;Given client ID does not match authenticated client&#34;);
   }
  }
  if (authenticatedClient !&#61; null) {
   oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient);
  }
  if (!StringUtils.hasText(tokenRequest.getGrantType())) {
   throw new InvalidRequestException(&#34;Missing grant type&#34;);
  }
  if (tokenRequest.getGrantType().equals(&#34;implicit&#34;)) {
   throw new InvalidGrantException(&#34;Implicit grant type not supported from token endpoint&#34;);
  }

  if (isAuthCodeRequest(parameters)) {
   // The scope was requested or determined during the authorization step
   if (!tokenRequest.getScope().isEmpty()) {
    logger.debug(&#34;Clearing scope of incoming token request&#34;);
    tokenRequest.setScope(Collections.&lt;String&gt; emptySet());
   }
  }

  if (isRefreshTokenRequest(parameters)) {
   // A refresh token has its own default scopes, so we should ignore any added by the factory here.
   tokenRequest.setScope(OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE)));
  }

  OAuth2AccessToken token &#61; getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);
  if (token &#61;&#61; null) {
   throw new UnsupportedGrantTypeException(&#34;Unsupported grant type: &#34; &#43; tokenRequest.getGrantType());
  }

  return getResponse(token);

}
}
</code></pre>
<ul><li> <p>我们将需要的JWT信息封装成对象,然后放入到我们的通用返回结果的<code>data</code>属性中去;</p> </li></ul>
<pre class="blockcode"><code>/**
* Oauth2获取Token返回信息封装
* Creat
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP