use*_*594 29 java security spring-security spring-security-oauth2
我正在尝试使用受Oauth2或Http-Basic身份验证保护的资源来实现API.
当我加载首先将http-basic身份验证应用于资源的WebSecurityConfigurerAdapter时,不接受Oauth2令牌身份验证.反之亦然.
示例配置: 这将http-basic身份验证应用于所有/ user/**资源
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private LoginApi loginApi;
@Autowired
public void setLoginApi(LoginApi loginApi) {
this.loginApi = loginApi;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new PortalUserAuthenticationProvider(loginApi));
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/users/**").authenticated()
.and()
.httpBasic();
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
Run Code Online (Sandbox Code Playgroud)
这将oauth令牌保护应用于/ user/**资源
@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.requestMatchers().antMatchers("/users/**")
.and()
.authorizeRequests()
.antMatchers("/users/**").access("#oauth2.clientHasRole('ROLE_CLIENT') and #oauth2.hasScope('read')");
}
}
Run Code Online (Sandbox Code Playgroud)
我确定有一些我遗漏的魔法代码告诉spring如果第一次失败会尝试两者?
任何援助都将非常感激.
小智 35
我根据迈克尔雷斯勒的回答提示了这项工作,但进行了一些调整.
我的目标是在同一资源端点上允许Basic Auth和Oauth,例如/ leafcase/123.由于filterChains的排序,我被困了很长时间(可以在FilterChainProxy.filterChains中检查); 默认顺序如下:
由于资源服务器的filterChains排名高于WebSecurityConfigurerAdapter配置的filterchain,并且前者几乎匹配每个资源端点,因此Oauth资源服务器逻辑总是会对资源端点的任何请求启动(即使请求使用Authorization:Basic标头).你会得到的错误是:
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
Run Code Online (Sandbox Code Playgroud)
我做了2个更改来完成这项工作:
首先,将WebSecurityConfigurerAdapter命令高于资源服务器(订单2高于订单3).
@Configuration
@Order(2)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
Run Code Online (Sandbox Code Playgroud)
其次,让configure(HttpSecurity)使用仅匹配"Authorization:Basic"的客户RequestMatcher.
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.anonymous().disable()
.requestMatcher(new BasicRequestMatcher())
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(oAuth2AuthenticationEntryPoint())
.and()
// ... other stuff
}
...
private static class BasicRequestMatcher implements RequestMatcher {
@Override
public boolean matches(HttpServletRequest request) {
String auth = request.getHeader("Authorization");
return (auth != null && auth.startsWith("Basic"));
}
}
Run Code Online (Sandbox Code Playgroud)
因此,在资源服务器的filterChain有机会匹配它之前,它匹配并处理Basic Auth资源请求.它还只处理Authorizaiton:基本资源请求,因此任何具有Authorization:Bearer的请求都将通过,然后由资源服务器的filterChain处理(即,Oauth的过滤器启动).此外,它的排名低于AuthenticationServer(如果在同一个项目上启用了AuthenticationServer),因此它不会阻止AuthenticaitonServer的过滤链处理对/ oauth/token等的请求.
这可能接近你想要的:
@Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatcher(new OAuthRequestedMatcher())
.authorizeRequests()
.anyRequest().authenticated();
}
private static class OAuthRequestedMatcher implements RequestMatcher {
@Override
public boolean matches(HttpServletRequest request) {
String auth = request.getHeader("Authorization");
// Determine if the client request contained an OAuth Authorization
return (auth != null) && auth.startsWith("Bearer");
}
}
Run Code Online (Sandbox Code Playgroud)
如果身份验证不成功,那么唯一没有提供的方法是"退回".
对我来说,这种方法是有道理的.如果用户通过基本身份验证直接向请求提供身份验证,则无需OAuth.如果客户端是代理客户端,那么我们需要此过滤器进入并确保请求已正确验证.
我认为不可能同时拥有这两种身份验证。您可以使用基本身份验证和 oauth2 身份验证,但针对不同的端点。正如您所做的那样,第一个配置将克服第二个配置,在这种情况下,将使用 http basic。
| 归档时间: |
|
| 查看次数: |
22484 次 |
| 最近记录: |