无需访问令牌即可访问 spring oauth2 保护的资源
Can access spring oauth2 protected resource without access token
使用:
- spring-security 3.2.5
- spring-security-oauth 2.0.7 (oauth2)
- grant_type : authentication_code
我获取 authentication_code 和访问令牌没有问题。
我遇到的问题是,如果我调用 "protected" 资源,我根本不需要令牌就可以访问它。这是 "not-really-protected" 资源的安全配置:
<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 说
No token in request, will continue chain.
我发现 this other post 似乎描述了同样的问题,但提出的解决方案是添加 <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
,我已经有了。
另外,tough可能不相关,对受保护资源的请求接收àSet-cookie
header,定义一个jsessionid。这对我来说似乎不正常,因为我指定 create-session="never"
.
自从我使用 OAuth2AccessDeniedHandler 以来,我预计会对该资源进行未经授权的调用 return 403。
有人可以帮我解决这个问题吗?
请注意,我非常确定此安全配置正在启动,因为在我的受保护资源(spring-mvc 控制器)中,SecurityContextHolder.getContext().getAuthentication()
return 为空。如果我完全禁用上述安全配置,同一行 returns 匿名身份验证。
编辑:详细配置信息。
首先我有令牌点配置:
<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>
然后 "generic" url 配置:
<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>
我相信你错过了 "Authorization" header。
您需要在 header 值中具有 "Bearer" 的值。
参考:
您的配置中有问题的部分是 <security:http pattern="/api/user/**" ...>
由于"pattern"属性设置为/api/user/**,你的拦截-url"pattern"属性
<security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
除非具有相同的前缀 (/api/user/**),否则不会有任何效果。
如果您尝试将 IS_AUTHENTICATED_FULLY 仅用于 /api/user/** 模式,则拦截-url 应该是
<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>
我找到了问题的原因,它非常针对我们的应用程序。
在配置的其他地方,我们覆盖了内置的 FilterInvocationSecurityMetadataSource(使用一个邪恶的 bean post-处理器)来添加一个自定义的。这具有禁用配置文件中所有 <intercept-url>
的效果。我们这样做是因为我们将遗留的自定义安全框架迁移到 spring-security 并希望在我们现有的文件中保持 url 安全。
感谢所有提供帮助的人。
使用:
- spring-security 3.2.5
- spring-security-oauth 2.0.7 (oauth2)
- grant_type : authentication_code
我获取 authentication_code 和访问令牌没有问题。 我遇到的问题是,如果我调用 "protected" 资源,我根本不需要令牌就可以访问它。这是 "not-really-protected" 资源的安全配置:
<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 说
No token in request, will continue chain.
我发现 this other post 似乎描述了同样的问题,但提出的解决方案是添加 <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
,我已经有了。
另外,tough可能不相关,对受保护资源的请求接收àSet-cookie
header,定义一个jsessionid。这对我来说似乎不正常,因为我指定 create-session="never"
.
自从我使用 OAuth2AccessDeniedHandler 以来,我预计会对该资源进行未经授权的调用 return 403。
有人可以帮我解决这个问题吗?
请注意,我非常确定此安全配置正在启动,因为在我的受保护资源(spring-mvc 控制器)中,SecurityContextHolder.getContext().getAuthentication()
return 为空。如果我完全禁用上述安全配置,同一行 returns 匿名身份验证。
编辑:详细配置信息。
首先我有令牌点配置:
<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>
然后 "generic" url 配置:
<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>
我相信你错过了 "Authorization" header。 您需要在 header 值中具有 "Bearer" 的值。
参考:
您的配置中有问题的部分是 <security:http pattern="/api/user/**" ...>
由于"pattern"属性设置为/api/user/**,你的拦截-url"pattern"属性
<security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
除非具有相同的前缀 (/api/user/**),否则不会有任何效果。
如果您尝试将 IS_AUTHENTICATED_FULLY 仅用于 /api/user/** 模式,则拦截-url 应该是
<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>
我找到了问题的原因,它非常针对我们的应用程序。
在配置的其他地方,我们覆盖了内置的 FilterInvocationSecurityMetadataSource(使用一个邪恶的 bean post-处理器)来添加一个自定义的。这具有禁用配置文件中所有 <intercept-url>
的效果。我们这样做是因为我们将遗留的自定义安全框架迁移到 spring-security 并希望在我们现有的文件中保持 url 安全。
感谢所有提供帮助的人。