我正在尝试用受Oauth2或Http-Basic身份验证保护的资源实现API。
当我加载WebSecurityConfigurerAdapter(它首先对资源应用http-basic身份验证)时,Oauth2令牌身份验证不被接受,反之亦然。
**配置示例:**这将对所有/user/**资源应用http基本身份验证
@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();
}
}
这将对/user/**资源应用oauth令牌保护
@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')");
}
}
我敢肯定,有一些神奇的代码,我错过了告诉Spring尝试两个如果第一个失败?
如有任何帮助,我们将不胜感激。
9条答案
按热度按时间r1zk6ea11#
我设法得到这个工作的基础上提示迈克尔雷斯勒的答案,但与一些调整。
我的目标是在相同的资源端点上同时允许Basic Auth和Oauth,例如/leafcase/123。由于filterChains的顺序(可以在FilterChainProxy中检查),我被困了很长一段时间;缺省顺序如下:
由于资源服务器的filterChains的排名高于WebSecurityConfigurerAdapter配置的filterchain,并且前者几乎匹配每个资源端点,因此Oauth资源服务器逻辑总是为任何到资源端点的请求启动(即使请求使用Authorization:Basic头)。
我做了2个更改以获得此工作:
首先,WebSecurityConfigurerAdapter的顺序高于资源服务器(顺序2高于顺序3)。
其次,让configure(HttpSecurity)使用一个客户RequestMatcher,它只匹配“Authorization:基本”。
因此,它会在资源服务器的filterChain有机会匹配一个基本身份验证资源请求之前,匹配并处理该请求。它还只处理Authorization:Basic资源请求,因此任何带有Authorization:Bearer的请求都将失败,然后由资源服务器的filterChain处理(即Oauth的过滤器生效)。此外,它的级别低于AuthenticationServer(如果AuthenticationServer在同一个项目上启用),因此它不会阻止AuthenticationServer的filterchain处理对/oauth/token的请求,等等。
ws51t4hk2#
这可能接近你要找的内容:
唯一没有提供的是,如果身份验证不成功,可以“后退”。
对我来说,这种方法是有意义的。如果一个用户直接通过Basic auth向请求提供身份验证,那么OAuth就没有必要了。如果客户端是一个代理,那么我们需要这个过滤器介入并确保请求得到正确的身份验证。
0sgqnhkj3#
为什么不反过来做呢?如果没有附加令牌,就绕过资源服务器,然后退回到正常的安全筛选器链。这是资源服务器筛选器停止的方式。
cetgtptt4#
@kca2ply提供的解决方案非常好用。我注意到浏览器没有发出挑战,所以我对代码做了一些调整,如下所示:
同时使用
requestMatcher()
和antMatcher()
可以使事情完美地运行。浏览器和HTTP客户端现在将首先质询基本凭据(如果尚未提供)。如果未提供凭据,则福尔斯OAuth2。bejyjqdl5#
您可以将BasicAuthenticationFilter添加到安全筛选器链中,以获取受保护资源上的OAuth2 OR基本身份验证安全。示例配置如下...
yvt65v4c6#
不能提供给你完整的例子,但这里有一个可以挖掘的提示:
粗略地说,springauth只是从请求(头)中提取auth数据请求过滤器和为该auth提供身份验证对象的身份验证管理器的组合。
因此,要在同一个url上获得基本和oauth,您需要在过滤器链BasicAuthenticationFilter和OAuth2AuthenticationProcessingFilter中安装2个过滤器。
我认为问题在于ConfiguringAdapters适合于更简单的配置,因为它们倾向于相互覆盖。
call to
ResourceServerConfiguration
请注意,您还需要提供2个不同的身份验证管理器:一个用于基本身份验证,一个用于Oauthddarikpa7#
如果有人试图让Spring WebFlux使用这个方法,那么确定是否处理请求的方法称为“securityMatcher”,而不是“requestMatcher”。
也就是说
siotufzp8#
我认为这是不可能的,有两个身份验证。你可以有基本身份验证和oauth2身份验证,但不同的端点。的方式,因为你做了,第一个配置将克服第二个,在这种情况下,http基本将被使用。
nnvyjq4y9#
在最新版本的Spring Boot中,WebSecurityConfigurerAdapter类别已停用。
要使某些端点具有HTTP基本授权,而使其他端点具有Oauth2授权,解决方案是在HttpSecurityFilterChain Bean调用中的Oauth2配置调用之前设置HTTP基本配置调用。例如:
其中,jwtDecoder()必须是在配置类中定义的Bean,如下所示:
此外,您还应该在配置中定义UserDetailsService Bean,例如,对于开发Porpuse而言,最简单的方法是定义InMemoryUserDetailsManager:
其中{bcrypt}用于解码存储在某个地方的密码,例如,在数据库表中。如果密码是纯文本的,您也可以在密码前面使用{noop}(不推荐,除非用于测试和开发目的)
所有这些Bean都应在类中定义,注解如下:
并且不要忘记在配置文件中指定JWT发布者URI,以便Oauth2正常工作: