调用/oauth/authorize接口时,代码首先进入org.springframework.web.method.support.InvocableHandlerMethod类的invokeForRequest方法;代码如下:

@Nullablepublic Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);if (logger.isTraceEnabled()) {logger.trace("Invoking '" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +"' with arguments " + Arrays.toString(args));}Object returnValue = doInvoke(args);if (logger.isTraceEnabled()) {logger.trace("Method [" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +"] returned [" + returnValue + "]");}return returnValue;}

通过Object returnValue = doInvoke(args);方法调用org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint类的authorize方法;

 @RequestMapping(value = "/oauth/authorize")public ModelAndView authorize(Map<String, Object> model, @RequestParam Map<String, String> parameters,SessionStatus sessionStatus, Principal principal) {// Pull out the authorization request first, using the OAuth2RequestFactory. All further logic should// query off of the authorization request instead of referring back to the parameters map. The contents of the// parameters map will be stored without change in the AuthorizationRequest object once it is created.AuthorizationRequest authorizationRequest = getOAuth2RequestFactory().createAuthorizationRequest(parameters);Set<String> responseTypes = authorizationRequest.getResponseTypes();if (!responseTypes.contains("token") && !responseTypes.contains("code")) {throw new UnsupportedResponseTypeException("Unsupported response types: " + responseTypes);}if (authorizationRequest.getClientId() == null) {throw new InvalidClientException("A client id must be provided");}try {if (!(principal instanceof Authentication) || !((Authentication) principal).isAuthenticated()) {throw new InsufficientAuthenticationException("User must be authenticated with Spring Security before authorization can be completed.");}ClientDetails client = getClientDetailsService().loadClientByClientId(authorizationRequest.getClientId());// The resolved redirect URI is either the redirect_uri from the parameters or the one from// clientDetails. Either way we need to store it on the AuthorizationRequest.String redirectUriParameter = authorizationRequest.getRequestParameters().get(OAuth2Utils.REDIRECT_URI);String resolvedRedirect = redirectResolver.resolveRedirect(redirectUriParameter, client);if (!StringUtils.hasText(resolvedRedirect)) {throw new RedirectMismatchException("A redirectUri must be either supplied or preconfigured in the ClientDetails");}authorizationRequest.setRedirectUri(resolvedRedirect);// We intentionally only validate the parameters requested by the client (ignoring any data that may have// been added to the request by the manager).oauth2RequestValidator.validateScope(authorizationRequest, client);// Some systems may allow for approval decisions to be remembered or approved by default. Check for// such logic here, and set the approved flag on the authorization request accordingly.authorizationRequest = userApprovalHandler.checkForPreApproval(authorizationRequest,(Authentication) principal);// TODO: is this call necessary?boolean approved = userApprovalHandler.isApproved(authorizationRequest, (Authentication) principal);authorizationRequest.setApproved(approved);// Validation is all done, so we can check for auto approval...if (authorizationRequest.isApproved()) {if (responseTypes.contains("token")) {return getImplicitGrantResponse(authorizationRequest);}if (responseTypes.contains("code")) {return new ModelAndView(getAuthorizationCodeResponse(authorizationRequest,(Authentication) principal));}}// Place auth request into the model so that it is stored in the session// for approveOrDeny to use. That way we make sure that auth request comes from the session,// so any auth request parameters passed to approveOrDeny will be ignored and retrieved from the session.model.put("authorizationRequest", authorizationRequest);return getUserApprovalPageResponse(model, authorizationRequest, (Authentication) principal);}catch (RuntimeException e) {sessionStatus.setComplete();throw e;}}

在这个方法中,如果principal为null时即生成User must be authenticated with Spring Security before authorization can be completed.异常。

         if (!(principal instanceof Authentication) || !((Authentication) principal).isAuthenticated()) {throw new InsufficientAuthenticationException("User must be authenticated with Spring Security before authorization can be completed.");}

principal在org.springframework.web.servlet.mvc.method.annotation.ServletRequestMethodArgumentResolver类的resolveArgument方法中生成的。在resolveArgument方法中第162行中 Principal userPrincipal = request.getUserPrincipal();如果request中不存在用户信息,则Principal 无法取得,造成参数为Null情况。

 @Nullableprivate Object resolveArgument(Class<?> paramType, HttpServletRequest request) throws IOException {if (HttpSession.class.isAssignableFrom(paramType)) {HttpSession session = request.getSession();if (session != null && !paramType.isInstance(session)) {throw new IllegalStateException("Current session is not of type [" + paramType.getName() + "]: " + session);}return session;}else if (pushBuilder != null && pushBuilder.isAssignableFrom(paramType)) {return PushBuilderDelegate.resolvePushBuilder(request, paramType);}else if (InputStream.class.isAssignableFrom(paramType)) {InputStream inputStream = request.getInputStream();if (inputStream != null && !paramType.isInstance(inputStream)) {throw new IllegalStateException("Request input stream is not of type [" + paramType.getName() + "]: " + inputStream);}return inputStream;}else if (Reader.class.isAssignableFrom(paramType)) {Reader reader = request.getReader();if (reader != null && !paramType.isInstance(reader)) {throw new IllegalStateException("Request body reader is not of type [" + paramType.getName() + "]: " + reader);}return reader;}else if (Principal.class.isAssignableFrom(paramType)) {Principal userPrincipal = request.getUserPrincipal();if (userPrincipal != null && !paramType.isInstance(userPrincipal)) {throw new IllegalStateException("Current user principal is not of type [" + paramType.getName() + "]: " + userPrincipal);}return userPrincipal;}else if (HttpMethod.class == paramType) {return HttpMethod.resolve(request.getMethod());}else if (Locale.class == paramType) {return RequestContextUtils.getLocale(request);}else if (TimeZone.class == paramType) {TimeZone timeZone = RequestContextUtils.getTimeZone(request);return (timeZone != null ? timeZone : TimeZone.getDefault());}else if (ZoneId.class == paramType) {TimeZone timeZone = RequestContextUtils.getTimeZone(request);return (timeZone != null ? timeZone.toZoneId() : ZoneId.systemDefault());}// Should never happen...throw new UnsupportedOperationException("Unknown parameter type: " + paramType.getName());}

OAuth2.0授权码/oauth/authorize接口调用unauthorized异常相关推荐

  1. oauth2.0授权码_OAUTH 2.0授权码授予

    oauth2.0授权码 OAuth 2.0提供了许多安全流程(或授权类型),以允许一个应用程序访问另一个应用程序中的用户数据. 在此博客中,我们将介绍OAuth 2.0授权:授权代码授权. 首先,有许 ...

  2. oauth2.0授权码模式详解

    Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/cou ...

  3. java 32位授权码_Java实现OAuth2.0授权码方式

    Java实现OAuth2.0授权码方式 前面介绍了OAuth2.0和授权方式,可以参考以下文章: 今天就用Java来验证OAuth2.0授权方式的授权码式,我们Spring Cloud的OAuth来实 ...

  4. OAuth2.0授权码模式学习

    OAuth2.0授权码模式学习 四种授权方式 1,授权码模式 2,简化模式 3,密码模式 4,客户端模式 授权码模式 四种授权模式中最完成,最严密的授权. (1)用户访问客户端,后者将前者导入认证服务 ...

  5. OAuth2.0 授权码认证方式使用流程

    第一步:获取授权码 /oauth/authorize?client_id=c1&response_type=code&scope=all&redirect_uri=http:/ ...

  6. OAuth2.0授权码模式原理与实战

    OAuth2.0是目前比较流行的一种开源授权协议,可以用来授权第三方应用,允许在不将用户名和密码提供给第三方应用的情况下获取一定的用户资源,目前很多网站或APP基于微信或QQ的第三方登录方式都是基于O ...

  7. OAuth2.0授权码模式实战

    OAuth2.0是目前比较流行的一种开源授权协议,可以用来授权第三方应用,允许在不将用户名和密码提供给第三方应用的情况下获取一定的用户资源,目前很多网站或APP基于微信或QQ的第三方登录方式都是基于O ...

  8. OAuth2.0授权码认证流程介绍

    Oauth2授权模式 Oauth2授权模式 Oauth2有以下授权模式: 1.授权码模式(Authorization Code) 2.隐式授权模式(Implicit)  3.密码模式(Resource ...

  9. 基于go-oauth2/oauth2实现OAuth 2.0 授权码方式

    前言 本文基于go-oauth2/oauth2,参考go-oauth2/oauth2/example.go-oauth2/gin-server.llaoj/oauth2,结合beego框架实现OAut ...

最新文章

  1. 网站如何进行渠道跟踪_开发网站不知道如何进行推广?5个技巧教会你
  2. 关于C#中async/await中的异常处理(上)
  3. Eclipse中怎样修改jar包的源码并将原jar包替换
  4. i节点详解以及软连接和硬链接的区别
  5. 常用串口调试工具比较
  6. 集成UG和ANSYS之二----upupdate之x_t
  7. JS每日一题:vue中keepalive怎么理解?
  8. select函数返回值_Vue学习笔记之函数、高阶函数、v-model的应用
  9. python logger.debug_python处理logger日志
  10. 基于PC端的爬取公众号历史文章
  11. 网络安全笔记(一)网络安全设备
  12. 网络安全工程师面试分享
  13. 三星手机和计算机如何连接打印机,三星打印机连接到电脑没反应怎么办
  14. Nyquist-Shannon采样定理的理解
  15. 源码分析 | 手写mybait-spring核心功能(干货好文一次学会工厂bean、类代理、bean注册的使用)
  16. 德邦维新:如何打赢“未来之战”?
  17. 商业模式创新与设计 -- 黄力泓
  18. Power BI /Power BI Pro账户等基本概念介绍
  19. 计算机网络连接在哪,本地连接在哪里找【四种方法】
  20. 设计模式与软考试题之状态模式(二)

热门文章

  1. 利用 Python 获取余额宝历史收益数据
  2. iOS 开发问与答(56-84)
  3. 重装系统 (小白版)
  4. android中oncreate方法,Android textView 中 onCreate 方法的改变
  5. php+控制器中的全局变量,php中的全局变量引用
  6. 力扣—679—24点游戏
  7. Visio 图形大小如何随文字多少自动调整?
  8. 微信支付分正式上线:马化腾在朋友圈四处挑战,10分钟后被打败
  9. 【详记MySql问题大全集】一、安装MySql
  10. 二叉堆--insert操作以及deleteMin操作的实现(C语言)