Java Spring Security Oauth-发送令牌请求时需要基本访问身份验证
我对SpringSecurityOAuth2.0有一个问题 spring security的基本配置取自示例:Java Spring Security Oauth-发送令牌请求时需要基本访问身份验证,java,spring,spring-mvc,oauth,spring-security,Java,Spring,Spring Mvc,Oauth,Spring Security,我对SpringSecurityOAuth2.0有一个问题 spring security的基本配置取自示例: <http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security"> <int
<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" />
<custom-filter ref="clientCredentialsTokenEndpointFilter"
after="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<http pattern="/path/**" 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="/path/*" 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="path" />
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="path/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>
<bean id="oauthAuthenticationProvider" class="my.package.OAuthAuthenticationProvider" xmlns="http://www.springframework.org/schema/beans" />
<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 ref="oauthAuthenticationProvider" />
</authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.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>
<bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler">
<property name="tokenServices" ref="tokenServices" />
</bean>
<!-- authorization-server aka AuthorizationServerTokenServices is an interface
that defines everything necessary for token management -->
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password />
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter"
resource-id="test" token-services-ref="tokenServices" />
<!-- ClientsDeailsService: Entry Point to clients database (given is in
memory implementation) -->
<oauth:client-details-service id="clientDetails">
<!-- client -->
<oauth:client client-id="the_client"
authorized-grant-types="authorization_code,client_credentials"
authorities="ROLE_USER" scope="read,write,trust" secret="secret" />
<oauth:client client-id="my-trusted-client-with-secret"
authorized-grant-types="password,authorization_code,refresh_token,implicit"
secret="somesecret" authorities="ROLE_USER" />
</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" />
Web浏览器要求登录名和密码(基本访问身份验证)
我需要在登录字段中输入客户端id,在密码字段中输入密码
生成对oauth的请求,然后调用my.package.OAuthAuthenticationProvider中的身份验证方法
我应该做些什么来避免这种基本的身份验证提示?您在servlet和过滤器映射方面的问题源于这样一个事实,即Spring OAuth需要一个DispatcherServlet用于其OAuth相关的端点。我建议您将它们放在默认的servlet映射(/)中,但这取决于您。在任何情况下,一站式安全配置都是servlet配置文件,而不是根上下文(因此需要使用DispatcherServlet
而不是ContextLoaderListener来加载它)。这与示例中的相同(您需要web.xml中的servlet init param),但是没有什么可以阻止您添加自己的附加servlet(当然,只要映射不冲突)
认证问题是不同的。OAuth2规范建议使用基本身份验证保护/token端点,因此提示原则上是一件好事,尽管我可以看到您试图避免它。像您这样在表单字段中放置机密实际上不够安全,无法在生产系统中使用,但如果出于某种原因需要,您可以使用ClientCredentialsTokenEndpointFilter
(就像您所做的那样)。筛选器不起作用的原因可能是因为您正在发送GET(而不是POST),出于安全目的,这比首先使用筛选器更糟糕,但我没有看到在筛选器中的任何位置设置标志来打开仅POST验证(尽管我建议你在任何地方愤怒地使用这个东西时设置它)
您没有显示2个Spring XML文件,但您的web.XML引用了2。我认为问题最终会归结为您将它们混合在一起或在这两个文件中复制了bean定义。也许您可以澄清这一点(或者按照上面的建议从DispatcherServlet
加载单个文件)?您可以使用如下配置避免登录页面:
...
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-security.xml</param-value>
</context-param>
...
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
...
<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>
...
<servlet>
<servlet-name>Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
...
<servlet-mapping>
<servlet-name>Dispatcher Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
...
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests()
.antMatchers("/").permitAll()
.and()
.authorizeRequests().anyRequest().hasRole("USER")
.and()
.csrf()
.requireCsrfProtectionMatcher(new AntPathRequestMatcher("/**")).disable();
// @formatter:on
}
...
}
默认情况下,此方法包括登录页面。如果您尝试在没有令牌的情况下执行请求,则会显示403错误页面(您还可以管理此错误以重定向到自定义页面)感谢您的回复。我正在另一个项目中使用spring oauth。我必须使用默认的servlet映射,但这是可能的(该应用程序不在产品上运行:)。如果没有连接到ContextLoaderListener的spring安全配置文件,spring安全将无法启动。但在第二个应用程序中,基本身份验证并没有要求客户端id和密码,通过GET请求参数传递它就足够进行身份验证了。。。当我将Dispatcher Servlet映射更改为默认映射时,这里也会发生同样的情况。我想我记得您还没有启用非默认servlet映射所需的设置—必须显式设置身份验证和令牌端点URL。我需要(明天)再看一次更详细的内容,看看能否用更多的信息更新答案,但也许这会让你开始。再次感谢你的帮助。现在我使用POST方法和其他发送基本身份验证凭据的方法,它似乎工作正常。我应该如何设置这个“POST only”验证器?还有一个问题-如何正确发送令牌请求-我需要一个安全的解决方案。现在我只改变了从GET到POST的方法。(我已经在使用SSL)仅POST验证在ClientCredentialsTokenEndpointFilter
中。最好不要使用该过滤器,而是对客户端使用其他更安全的身份验证(您已经启用了HTTP Basic,这就是为什么您的浏览器会在手动测试中提示您的原因)。任何HTTP客户端都将支持基本身份验证(检查文档)。
<servlet-mapping>
<servlet-name>Dispatcher Servlet</servlet-name>
<url-pattern>/somepath/*</url-pattern>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<http pattern="/somepath/oauth/token" create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/somepath/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<custom-filter ref="clientCredentialsTokenEndpointFilter"
after="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
...
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests()
.antMatchers("/").permitAll()
.and()
.authorizeRequests().anyRequest().hasRole("USER")
.and()
.csrf()
.requireCsrfProtectionMatcher(new AntPathRequestMatcher("/**")).disable();
// @formatter:on
}
...
}