2014-09-03 79 views
6

我已經創建了一個RESTful web服務來對工作流執行操作。 Web服務使用我自己的授權服務器通過oauth2進行保護。 我想向我的工作流程添加關於誰對其執行操作的信息。我無法弄清楚誰來獲取調用Web服務的用戶名。Spring安全oauth2:在REST webservice中獲取用戶名

對於Web服務實現,我使用球衣(1.18.1)和我使用spring-security-oauth2(2.0.2.RELEASE)的安全性。

我正在使用一個數據庫令牌存儲,它包含一個看起來像包含正確信息的表OAUTH_ACCESS_TOKEN(TOKEN_ID,TOKEN,AUTHENTICATION_ID,USER_NAME,CLIENT_ID,AUTHENTICATION,REFRESH_TOKEN)。它有用戶名和標記,但標記看起來像一個序列化的java對象,所以我不能自己查詢它。

Web服務:

@Component 
@Path("/workflows") 
public class WorkflowRestService { 

    @POST 
    @Path("/{id}/actions") 
    @Produces(MediaType.APPLICATION_JSON) 
    @Transactional 
    public Response executeActions(@PathParam("id") String id, Map<String, Object> actionArgs) throws JAXBException, HealthDataException { 

     //would like to have/get username here. 

     Workflow workflow = workflowService.get(id); 
     Action action = actionFactory.getAction(actionArgs); 
     workflow.execute(action); 
     Workflow update = workflowService.update(workflow); 
     return Response.ok(update).build(); 
    } 
} 

Web服務安全性配置:

<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xmlns:oauth="http://www.springframework.org/schema/security/oauth2" 
     xmlns:sec="http://www.springframework.org/schema/security" 
     xsi:schemaLocation="http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context-3.2.xsd 
     http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
     http://www.springframework.org/schema/security 
     http://www.springframework.org/schema/security/spring-security-3.2.xsd 
     http://www.springframework.org/schema/security/oauth2 
     http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd"> 

    <context:property-placeholder location="classpath:main.properties"/> 

    <!-- Protected resources --> 
    <http authentication-manager-ref="" pattern="/workflows/**" 
      create-session="never" 
      entry-point-ref="oauthAuthenticationEntryPoint" 
      access-decision-manager-ref="accessDecisionManager" 
      xmlns="http://www.springframework.org/schema/security"> 
     <anonymous enabled="false"/> 
     <intercept-url pattern="/workflows/**" 
         access="ROLE_USER"/> 
     <custom-filter ref="resourceServerFilter" 
         before="PRE_AUTH_FILTER"/> 
     <access-denied-handler 
       ref="oauthAccessDeniedHandler"/> 
    </http> 

    <bean id="oauthAuthenticationEntryPoint" 
      class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"> 
     <property name="realmName" value="dstest"/> 
    </bean> 

    <bean id="oauthAccessDeniedHandler" 
      class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler"/> 

    <bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased" 
      xmlns="http://www.springframework.org/schema/beans"> 
     <constructor-arg> 
      <list> 
       <bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter"/> 
       <bean class="org.springframework.security.access.vote.RoleVoter"/> 
       <bean class="org.springframework.security.access.vote.AuthenticatedVoter"/> 
      </list> 
     </constructor-arg> 
    </bean> 

    <authentication-manager alias="authenticationManager" xmlns="http://www.springframework.org/schema/security"> 
     <authentication-provider> 
      <jdbc-user-service data-source-ref="securityDataSource"/> 
     </authentication-provider> 
    </authentication-manager> 

    <bean id="clientDetailsUserService" 
      class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService"> 
     <constructor-arg ref="clientDetails"/> 
    </bean> 

    <!-- Token Store --> 
    <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore"> 
     <constructor-arg ref="securityDataSource" /> 
    </bean> 

    <bean id="oAuth2RequestFactory" class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory"> 
     <constructor-arg ref="clientDetails"/> 
    </bean> 

    <bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices"> 
     <property name="tokenStore" ref="tokenStore"/> 
     <property name="supportRefreshToken" value="true"/> 
     <property name="clientDetailsService" ref="clientDetails"/> 
     <!-- VIV --> 
     <property name="accessTokenValiditySeconds" value="10"/> 
    </bean> 

    <oauth:resource-server id="resourceServerFilter" 
          resource-id="dstest" 
          token-services-ref="tokenServices"/> 

    <!-- Client Definition --> 
    <oauth:client-details-service id="clientDetails"> 

     <oauth:client client-id="healthdata-client" 
         authorized-grant-types="password,authorization_code,refresh_token,implicit,redirect" 
         authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT" 
         redirect-uri="/web" 
         scope="read,write,trust" 
         access-token-validity="300" 
         refresh-token-validity="6000"/> 

    </oauth:client-details-service> 


    <sec:global-method-security pre-post-annotations="enabled" proxy-target-class="true"> 
     <sec:expression-handler ref="oauthExpressionHandler"/> 
    </sec:global-method-security> 
    <oauth:expression-handler id="oauthExpressionHandler"/> 
    <oauth:web-expression-handler id="oauthWebExpressionHandler"/> 
</beans> 

授權服務器配置:

<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xmlns:oauth="http://www.springframework.org/schema/security/oauth2" 
     xmlns:sec="http://www.springframework.org/schema/security" 
     xsi:schemaLocation="http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context-3.2.xsd 
     http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
     http://www.springframework.org/schema/security 
     http://www.springframework.org/schema/security/spring-security-3.2.xsd 
     http://www.springframework.org/schema/security/oauth2 
     http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd"> 

    <context:property-placeholder location="classpath:main.properties"/> 

    <!-- Definition of the Authentication Service --> 
    <http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" 
      xmlns="http://www.springframework.org/schema/security"> 
     <intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY"/> 
     <anonymous enabled="false"/> 
     <http-basic entry-point-ref="clientAuthenticationEntryPoint"/> 
     <!--  include this only if you need to authenticate clients via request parameters --> 
     <custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER"/> 
     <access-denied-handler ref="oauthAccessDeniedHandler"/> 
    </http> 

    <!-- Protected resources --> 
    <http pattern="https://stackoverflow.com/users/**" 
      create-session="never" 
      entry-point-ref="oauthAuthenticationEntryPoint" 
      access-decision-manager-ref="accessDecisionManager" 
      xmlns="http://www.springframework.org/schema/security"> 
     <anonymous enabled="false"/> 
     <intercept-url pattern="https://stackoverflow.com/users/**" 
         access="ROLE_USER"/> 
     <custom-filter ref="resourceServerFilter" 
         before="PRE_AUTH_FILTER"/> 
     <access-denied-handler 
       ref="oauthAccessDeniedHandler"/> 
    </http> 

    <bean id="oauthAuthenticationEntryPoint" 
      class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"> 
     <property name="realmName" value="dstest"/> 
    </bean> 

    <bean id="clientAuthenticationEntryPoint" 
      class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"> 
     <property name="realmName" value="dstest/client"/> 
     <property name="typeName" value="Basic"/> 
    </bean> 

    <bean id="oauthAccessDeniedHandler" 
      class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler"/> 

    <bean id="clientCredentialsTokenEndpointFilter" 
      class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter"> 
     <property name="authenticationManager" ref="clientAuthenticationManager"/> 
    </bean> 

    <bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased" 
      xmlns="http://www.springframework.org/schema/beans"> 
     <constructor-arg> 
      <list> 
       <bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter"/> 
       <bean class="org.springframework.security.access.vote.RoleVoter"/> 
       <bean class="org.springframework.security.access.vote.AuthenticatedVoter"/> 
      </list> 
     </constructor-arg> 
    </bean> 

    <!-- Authentication in config file --> 
    <authentication-manager id="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security"> 
     <authentication-provider user-service-ref="clientDetailsUserService"/> 
    </authentication-manager> 

    <authentication-manager alias="authenticationManager" xmlns="http://www.springframework.org/schema/security"> 
     <authentication-provider> 
      <jdbc-user-service data-source-ref="securityDataSource"/> 
     </authentication-provider> 
    </authentication-manager> 

    <bean id="clientDetailsUserService" 
      class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService"> 
     <constructor-arg ref="clientDetails"/> 
    </bean> 

    <!-- Token Store --> 
    <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore"> 
     <constructor-arg ref="securityDataSource" /> 
    </bean> 

    <bean id="oAuth2RequestFactory" class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory"> 
     <constructor-arg ref="clientDetails"/> 
    </bean> 

    <bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices"> 
     <property name="tokenStore" ref="tokenStore"/> 
     <property name="supportRefreshToken" value="true"/> 
     <property name="clientDetailsService" ref="clientDetails"/> 
     <!-- VIV --> 
     <property name="accessTokenValiditySeconds" value="10"/> 
    </bean> 

    <bean id="userApprovalHandler" 
      class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler"> 
     <property name="tokenStore" ref="tokenStore"/> 
     <property name="requestFactory" ref="oAuth2RequestFactory"/> 
    </bean> 

    <!-- Token management --> 
    <oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices" 
           user-approval-handler-ref="userApprovalHandler" token-endpoint-url="/oauth/token"> 
     <oauth:authorization-code/> 
     <oauth:implicit/> 
     <oauth:refresh-token/> 
     <oauth:client-credentials/> 
     <oauth:password/> 
    </oauth:authorization-server> 

    <oauth:resource-server id="resourceServerFilter" 
          resource-id="dstest" 
          token-services-ref="tokenServices"/> 

    <!-- Client Definition --> 
    <oauth:client-details-service id="clientDetails"> 

     <oauth:client client-id="healthdata-client" 
         authorized-grant-types="password,authorization_code,refresh_token,implicit,redirect" 
         authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT" 
         redirect-uri="/web" 
         scope="read,write,trust" 
         access-token-validity="300" 
         refresh-token-validity="6000"/> 

    </oauth:client-details-service> 


    <sec:global-method-security pre-post-annotations="enabled" proxy-target-class="true"> 
     <sec:expression-handler ref="oauthExpressionHandler"/> 
    </sec:global-method-security> 
    <oauth:expression-handler id="oauthExpressionHandler"/> 
    <oauth:web-expression-handler id="oauthWebExpressionHandler"/> 
</beans> 

回答

16

由於您使用Spring Security進行身份驗證我希望你有權訪問SecurityContext(通過常用的線程本地訪問器):

Authentication authentication = SecurityContextHolder.getContext() 
    .getAuthentication(); 

或通過HttpServletRequest

Principal principal = request.getUserPrincipal(); 

(或者如果你使用Spring MVC的只是添加Principal方法參數在@Controller)。無論哪種情況,由於您位於Spring OAuth篩選器後面,因此您還應該發現Principal/AuthenticationOAuth2Authentication的一個實例,並且用戶詳細信息以及客戶端都位於此處。

+1

我的確有權訪問SecurityContext,因此可以獲得校長。 – Xymon 2014-09-04 07:51:13

相關問題