无需访问令牌即可访问spring oauth2受保护资源

时间:2015-03-31 16:09:12

标签: java spring spring-security spring-security-oauth2

使用:

  • spring-security 3.2.5
  • spring-security-oauth 2.0.7(oauth2)
  • grant_type:authentication_code

获取authentication_code和访问令牌没有问题。 我遇到的问题是,如果我调用“受保护”资源,我可以访问它而根本没有令牌。以下是“未受实际保护”资源的安全配置:

<security:http pattern="/api/user/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint"
                  access-decision-manager-ref="accessDecisionManager">
  <security:anonymous enabled="false" />
  <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
  <security:custom-filter ref="userResourceServer" before="PRE_AUTH_FILTER" />
  <security:access-denied-handler ref="oauthAccessDeniedHandler" />
</security:http>

Oauth2AuthenticationProcessingFilter说

  

请求中没有令牌,将继续链。

我发现this other post似乎描述了同样的问题,但提出的解决方案是添加<security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />,我已经拥有了。{/ p>

此外,强硬可能不相关,对受保护资源的请求接收àSet-cookie标头,定义jsessionid。因为我指定create-session="never",这对我来说似乎不正常。

由于我使用OAuth2AccessDeniedHandler,我预计未经授权的对此资源的调用将返回403。

有人可以帮我这个吗?

请注意,我非常确定此安全配置正在启动,因为在我的受保护资源(spring-mvc控制器)中,SecurityContextHolder.getContext().getAuthentication()返回null。如果我完全禁用上述安全配置,则同一行将返回匿名身份验证。

编辑:详细的配置信息。

首先我有令牌enpoint配置:

  <security:http pattern="/api/oauth/token" 
               create-session="stateless" 
               authentication-manager-ref="clientAuthenticationManager">
    <security:intercept-url pattern="/api/oauth/token"
                            access="IS_AUTHENTICATED_FULLY" />
    <security:anonymous enabled="false" />
    <security:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
    <security:access-denied-handler ref="oauthAccessDeniedHandler" />
  </security:http>

然后是资源端点配置(如问题开头所示):

   <security:http pattern="/api/user/**" 
                  create-session="never" 
                  entry-point-ref="oauthAuthenticationEntryPoint"
                  access-decision-manager-ref="accessDecisionManager">
     <security:anonymous enabled="false" />
     <security:intercept-url pattern="/api/user/**"
                             access="IS_AUTHENTICATED_FULLY" />
     <security:custom-filter ref="userResourceServer"
                             before="PRE_AUTH_FILTER" />
     <security:access-denied-handler ref="oauthAccessDeniedHandler" />
   </security:http>

然后是“通用”网址配置:

<security:http name="genericSecurityConfiguration" entry-point-ref="customLoginEntrypoint">
    <security:form-login authentication-failure-url="/index.jsp"
                         authentication-success-handler-ref="customAuthenticationSuccessHandler"
                         authentication-failure-handler-ref="customAuthenticationFailureHandler"
                         login-page="/index.jsp"
                         login-processing-url="/solapCore/identification2"
                         username-parameter="username"
                         password-parameter="password"
                         />
    <security:session-management invalid-session-url="/index.jsp?invalidSession=true" session-authentication-strategy-ref="sas" /> 
    <security:custom-filter position="LOGOUT_FILTER" ref="logoutFilter"/>
    <security:custom-filter before="FILTER_SECURITY_INTERCEPTOR" ref="monitoringFilter"/>
    <security:access-denied-handler ref="solapcoreAccessDeniedHandler"/>
  </security:http>

同一文件中的其他oauth特定配置:

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

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

  <bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
    <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>

  <security:authentication-manager id="clientAuthenticationManager">
    <security:authentication-provider user-service-ref="clientDetailsUserService" />
  </security:authentication-manager>

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

  <oauth:authorization-server  
    client-details-service-ref="clientDetails" 
    token-services-ref="tokenServices" 
    user-approval-handler-ref="userApprovalHandler">
    <oauth:authorization-code />
  </oauth:authorization-server>

  <oauth:resource-server id="userResourceServer" 
                         resource-id="oauth2/user"  
                         token-services-ref="tokenServices" />

  <oauth:client-details-service id="clientDetails">
    <oauth:client client-id="someClientID" 
                  authorized-grant-types="authorization_code"
                  authorities="SOME_AUTHORITY" scope="read" secret="secret" />
  </oauth:client-details-service>

 <security:global-method-security pre-post-annotations="enabled" proxy-target-class="true">
   <security:expression-handler ref="oauthExpressionHandler" />
 </security:global-method-security>

 <oauth:expression-handler id="oauthExpressionHandler" />
 <oauth:web-expression-handler id="oauthWebExpressionHandler" />

 <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore" />

 <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" />
 </bean>

最后,我在web.xml中的调度程序servlet和filterChain配置:

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>
    org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/api/*</url-pattern>
</servlet-mapping>
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

3 个答案:

答案 0 :(得分:0)

答案 1 :(得分:0)

配置中有问题的部分是<security:http pattern="/api/user/**" ...>

自&#34;模式&#34;属性设置为/ api / user / **,你的intercept-url&#34;模式&#34;属性

<security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />

除非它具有相同的前缀(/ api / user /**)否则不会有任何效果。

如果您只是尝试将IS_AUTHENTICATED_FULLY用于/ api / user / **模式,那么拦截网址应为

<security:http pattern="/api/user/**" ...>
  <security:anonymous enabled="false" />
  <security:intercept-url pattern="/api/user/**" access="IS_AUTHENTICATED_FULLY" />
  <security:custom-filter ref="userResourceServer" before="PRE_AUTH_FILTER" />
  <security:access-denied-handler ref="oauthAccessDeniedHandler" />
</security:http>

如果您要将该规则应用于完整申请,那么这样的事情应该有效:

<security:http create-session="never" entry-point-ref="oauthAuthenticationEntryPoint"
                  access-decision-manager-ref="accessDecisionManager">
  <security:anonymous enabled="false" />
  <security:intercept-url pattern="/api/user/**" access="IS_AUTHENTICATED_FULLY" />
  <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
  <security:custom-filter ref="userResourceServer" before="PRE_AUTH_FILTER" />
  <security:access-denied-handler ref="oauthAccessDeniedHandler" />
</security:http>

答案 2 :(得分:0)

我找到了问题的原因,这对我们的应用非常具体。

配置中的其他地方,我们覆盖内置的FilterInvocationSecurityMetadataSource(使用邪恶的bean后处理器)来添加自定义的。这样可以禁用配置文件中的所有<intercept-url>。我们这样做是因为我们将传统的自定义安全框架迁移到spring-security,并希望在我们现有的文件中保留url安全性。

感谢所有想要帮助的人。