如何在运行时使用 spring 安全性切换安全模型?
How to switch security model in runtime with spring security?
如何在运行时切换安全模型,以便
- 现有的 spring 安全组件可以生成
Authentication
,并且
- 一个现有的 spring 安全组件可以验证
Authentication
我想我解决了 (2) 但不太明白 (1)。
Spring 安全配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").authenticated().and()
.addFilterBefore(switchingFilter);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(switchingAuthenticationProvider);
}
@Bean
public SwitchingAuthenticationProvider switchingAuthenticationProvider() {
return new SwitchingAuthenticationProvider();
}
@Bean
public SwitchingFilter switchingFilter() {
return new SwitchingFilter();
}
}
SwitchingAuthenticationProvider
很简单:只需委托给其他人 AuthenticationProvder
(即 LDAP/OAUTH2 或其他)
(灵感来自 Switching authentication approaches at runtime with Spring Security)。
public class SwitchingAuthenticationProvider implements AuthenticationProvider {
private AuthenticationProvider[] authProviders = // ...
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
return authProvider[i].authenticate(authentication);
}
}
但是是什么创造了 Authentication
?据我了解,一种选择是让 GenericFilterBean
创建 Authentication
,如下所示。
public class SwitchingFilter extends GenericFilterBean {
private AuthProviderService authProviders = // ...
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
Authentication authentication = authProviders.getAuthentication(request);
SecurityContextHolder.getContext().setAuthentication(authentication);
filterChain.doFilter(request, response);
SecurityContextHolder.getContext().setAuthentication(null);
}
}
... 其中 AuthProviderService
将委托给创建 authentication
的对象。但是我如何插入它,例如 HttpSecurity#httpBasic()
或 HttpSecurity#openIdLogin()
?
奖金问题:HttpSecurity#authenticationProvider(..)
和 AuthenticationManagerBuilder.authenticationProvider(..)
有什么区别?
似乎 Filter
是 负责创建 Authentication
(不确定是否还有其他内容也)。
以AnonymousAuthenticationFilter
为例
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
if (SecurityContextHolder.getContext().getAuthentication() == null) {
SecurityContextHolder.getContext().setAuthentication(
createAuthentication((HttpServletRequest) req));
}
类似我认为SwitchingFilter
应该类似于SwitchingAuthenticationProvider
public class SwitchingFilter extends GenericFilterBean {
private Filter[] filters = // ...
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
filters[i].doFilter(request, response, chain);
// do filterChain.doFilter(request, response); ??
}
}
.. 一些选择合适索引的机制i
。
如何在运行时切换安全模型,以便
- 现有的 spring 安全组件可以生成
Authentication
,并且 - 一个现有的 spring 安全组件可以验证
Authentication
我想我解决了 (2) 但不太明白 (1)。
Spring 安全配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").authenticated().and()
.addFilterBefore(switchingFilter);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(switchingAuthenticationProvider);
}
@Bean
public SwitchingAuthenticationProvider switchingAuthenticationProvider() {
return new SwitchingAuthenticationProvider();
}
@Bean
public SwitchingFilter switchingFilter() {
return new SwitchingFilter();
}
}
SwitchingAuthenticationProvider
很简单:只需委托给其他人 AuthenticationProvder
(即 LDAP/OAUTH2 或其他)
(灵感来自 Switching authentication approaches at runtime with Spring Security)。
public class SwitchingAuthenticationProvider implements AuthenticationProvider {
private AuthenticationProvider[] authProviders = // ...
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
return authProvider[i].authenticate(authentication);
}
}
但是是什么创造了 Authentication
?据我了解,一种选择是让 GenericFilterBean
创建 Authentication
,如下所示。
public class SwitchingFilter extends GenericFilterBean {
private AuthProviderService authProviders = // ...
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
Authentication authentication = authProviders.getAuthentication(request);
SecurityContextHolder.getContext().setAuthentication(authentication);
filterChain.doFilter(request, response);
SecurityContextHolder.getContext().setAuthentication(null);
}
}
... 其中 AuthProviderService
将委托给创建 authentication
的对象。但是我如何插入它,例如 HttpSecurity#httpBasic()
或 HttpSecurity#openIdLogin()
?
奖金问题:HttpSecurity#authenticationProvider(..)
和 AuthenticationManagerBuilder.authenticationProvider(..)
有什么区别?
似乎 Filter
是 负责创建 Authentication
(不确定是否还有其他内容也)。
以AnonymousAuthenticationFilter
为例
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
if (SecurityContextHolder.getContext().getAuthentication() == null) {
SecurityContextHolder.getContext().setAuthentication(
createAuthentication((HttpServletRequest) req));
}
类似我认为SwitchingFilter
应该类似于SwitchingAuthenticationProvider
public class SwitchingFilter extends GenericFilterBean {
private Filter[] filters = // ...
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
filters[i].doFilter(request, response, chain);
// do filterChain.doFilter(request, response); ??
}
}
.. 一些选择合适索引的机制i
。