赞
踩
spring security经常在项目中用到,但是平常只是简单的使用肯定是不够的,我们需要了解深层次的东西,才能在使用的过程中不畏惧,本次打算从demo入手,跟踪源码,剖析security内在
1、在之前的文章中我们看到AuthorizationServerEndpointsConfiguration配置中配置了AuthorizationEndpoint和TokenEndpoint等,他们都是继承自AbstractEndpoint
2、AuthorizationServerEndpointsConfiguration中创建了FrameworkEndpointHandlerMapping
这个RequestMappingHandlerMapping大家应该比较熟悉了,是mvc中的加载handler的类
现在我们看下FrameworkEndpointHandlerMapping的isHandler方法
至此应该清楚了,就是类上注解@FrameworkEndpoint的存在,将各个AbstractEndpoint的方法加载到servlet中
clent的认证我们上一篇文章中已经讲过了,现在我们继续剖析这个获取token的接口
首先我们倒推看下mvc中参数是如何解析并封装到方法中的
@Nullable private 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; } ... ... //从request中获取principal 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()); } ... // Should never happen... throw new UnsupportedOperationException("Unknown parameter type: " + paramType.getName()); }
从request中获取principal,此时的request的是
由于Servlet3SecurityContextHolderAwareRequestWrapper继承自SecurityContextHolderAwareRequestWrapper
回到参数解析流程,调用了request的getUserPrincipal方法,看下SecurityContextHolderAwareRequestWrapper的getUserPrincipal方法
至此返回了认证对象Authentication
@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."); } String clientId = getClientId(principal); ClientDetails authenticatedClient = getClientDetailsService().loadClientByClientId(clientId); TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient); if (clientId != null && !clientId.equals("")) { if (!clientId.equals(tokenRequest.getClientId())) { throw new InvalidClientException("Given client ID does not match authenticated client"); } } ... ... //获取tokenGranter OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest); if (token == null) { throw new UnsupportedGrantTypeException("Unsupported grant type: " + tokenRequest.getGrantType()); } return getResponse(token); }
此时的tokenGranter是AuthorizationServerEndpointsConfigurer的tokenGranter创建的匿名对象
默认5种授权类型(授权码模式(authorization_code)、刷新令牌(refresh_token)、简化模式(implicit)、客户端模式(client credentials)、密码模式(password)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。