当前位置:   article > 正文

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

/oauth/authorize

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

  1. @Nullable
  2. public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
  3. Object... providedArgs) throws Exception {
  4. Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
  5. if (logger.isTraceEnabled()) {
  6. logger.trace("Invoking '" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
  7. "' with arguments " + Arrays.toString(args));
  8. }
  9. Object returnValue = doInvoke(args);
  10. if (logger.isTraceEnabled()) {
  11. logger.trace("Method [" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
  12. "] returned [" + returnValue + "]");
  13. }
  14. return returnValue;
  15. }

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

  1. @RequestMapping(value = "/oauth/authorize")
  2. public ModelAndView authorize(Map<String, Object> model, @RequestParam Map<String, String> parameters,
  3. SessionStatus sessionStatus, Principal principal) {
  4. // Pull out the authorization request first, using the OAuth2RequestFactory. All further logic should
  5. // query off of the authorization request instead of referring back to the parameters map. The contents of the
  6. // parameters map will be stored without change in the AuthorizationRequest object once it is created.
  7. AuthorizationRequest authorizationRequest = getOAuth2RequestFactory().createAuthorizationRequest(parameters);
  8. Set<String> responseTypes = authorizationRequest.getResponseTypes();
  9. if (!responseTypes.contains("token") && !responseTypes.contains("code")) {
  10. throw new UnsupportedResponseTypeException("Unsupported response types: " + responseTypes);
  11. }
  12. if (authorizationRequest.getClientId() == null) {
  13. throw new InvalidClientException("A client id must be provided");
  14. }
  15. try {
  16. if (!(principal instanceof Authentication) || !((Authentication) principal).isAuthenticated()) {
  17. throw new InsufficientAuthenticationException(
  18. "User must be authenticated with Spring Security before authorization can be completed.");
  19. }
  20. ClientDetails client = getClientDetailsService().loadClientByClientId(authorizationRequest.getClientId());
  21. // The resolved redirect URI is either the redirect_uri from the parameters or the one from
  22. // clientDetails. Either way we need to store it on the AuthorizationRequest.
  23. String redirectUriParameter = authorizationRequest.getRequestParameters().get(OAuth2Utils.REDIRECT_URI);
  24. String resolvedRedirect = redirectResolver.resolveRedirect(redirectUriParameter, client);
  25. if (!StringUtils.hasText(resolvedRedirect)) {
  26. throw new RedirectMismatchException(
  27. "A redirectUri must be either supplied or preconfigured in the ClientDetails");
  28. }
  29. authorizationRequest.setRedirectUri(resolvedRedirect);
  30. // We intentionally only validate the parameters requested by the client (ignoring any data that may have
  31. // been added to the request by the manager).
  32. oauth2RequestValidator.validateScope(authorizationRequest, client);
  33. // Some systems may allow for approval decisions to be remembered or approved by default. Check for
  34. // such logic here, and set the approved flag on the authorization request accordingly.
  35. authorizationRequest = userApprovalHandler.checkForPreApproval(authorizationRequest,
  36. (Authentication) principal);
  37. // TODO: is this call necessary?
  38. boolean approved = userApprovalHandler.isApproved(authorizationRequest, (Authentication) principal);
  39. authorizationRequest.setApproved(approved);
  40. // Validation is all done, so we can check for auto approval...
  41. if (authorizationRequest.isApproved()) {
  42. if (responseTypes.contains("token")) {
  43. return getImplicitGrantResponse(authorizationRequest);
  44. }
  45. if (responseTypes.contains("code")) {
  46. return new ModelAndView(getAuthorizationCodeResponse(authorizationRequest,
  47. (Authentication) principal));
  48. }
  49. }
  50. // Place auth request into the model so that it is stored in the session
  51. // for approveOrDeny to use. That way we make sure that auth request comes from the session,
  52. // so any auth request parameters passed to approveOrDeny will be ignored and retrieved from the session.
  53. model.put("authorizationRequest", authorizationRequest);
  54. return getUserApprovalPageResponse(model, authorizationRequest, (Authentication) principal);
  55. }
  56. catch (RuntimeException e) {
  57. sessionStatus.setComplete();
  58. throw e;
  59. }
  60. }

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

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

 

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

  1. @Nullable
  2. private Object resolveArgument(Class<?> paramType, HttpServletRequest request) throws IOException {
  3. if (HttpSession.class.isAssignableFrom(paramType)) {
  4. HttpSession session = request.getSession();
  5. if (session != null && !paramType.isInstance(session)) {
  6. throw new IllegalStateException(
  7. "Current session is not of type [" + paramType.getName() + "]: " + session);
  8. }
  9. return session;
  10. }
  11. else if (pushBuilder != null && pushBuilder.isAssignableFrom(paramType)) {
  12. return PushBuilderDelegate.resolvePushBuilder(request, paramType);
  13. }
  14. else if (InputStream.class.isAssignableFrom(paramType)) {
  15. InputStream inputStream = request.getInputStream();
  16. if (inputStream != null && !paramType.isInstance(inputStream)) {
  17. throw new IllegalStateException(
  18. "Request input stream is not of type [" + paramType.getName() + "]: " + inputStream);
  19. }
  20. return inputStream;
  21. }
  22. else if (Reader.class.isAssignableFrom(paramType)) {
  23. Reader reader = request.getReader();
  24. if (reader != null && !paramType.isInstance(reader)) {
  25. throw new IllegalStateException(
  26. "Request body reader is not of type [" + paramType.getName() + "]: " + reader);
  27. }
  28. return reader;
  29. }
  30. else if (Principal.class.isAssignableFrom(paramType)) {
  31. Principal userPrincipal = request.getUserPrincipal();
  32. if (userPrincipal != null && !paramType.isInstance(userPrincipal)) {
  33. throw new IllegalStateException(
  34. "Current user principal is not of type [" + paramType.getName() + "]: " + userPrincipal);
  35. }
  36. return userPrincipal;
  37. }
  38. else if (HttpMethod.class == paramType) {
  39. return HttpMethod.resolve(request.getMethod());
  40. }
  41. else if (Locale.class == paramType) {
  42. return RequestContextUtils.getLocale(request);
  43. }
  44. else if (TimeZone.class == paramType) {
  45. TimeZone timeZone = RequestContextUtils.getTimeZone(request);
  46. return (timeZone != null ? timeZone : TimeZone.getDefault());
  47. }
  48. else if (ZoneId.class == paramType) {
  49. TimeZone timeZone = RequestContextUtils.getTimeZone(request);
  50. return (timeZone != null ? timeZone.toZoneId() : ZoneId.systemDefault());
  51. }
  52. // Should never happen...
  53. throw new UnsupportedOperationException("Unknown parameter type: " + paramType.getName());
  54. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/84063
推荐阅读
相关标签
  

闽ICP备14008679号