由于在 StackOverflow 上已经有很多关于这个问题的问题,我首先要确保这不是重复和区分。
这是关于
所以问题不在于:
假设有2个自定义authenticationprovider:CATApiTokenProvider和DOGApiTokenProvider。根据设计,我们不谈论auth/JWT/Basic/Form提供者,因为它们提供快捷方式。
现在我们有两个REST APIendpoint< code>/dog/endpoint和< code>/cat/endpoint。
今天如何使用Spring Security 5.5正确实现这一点:
CATApiTokenProvider
只能对/cat/endpoint
DOGApiTokenProvider
只能对/dog/endpoint
上的请求进行身份验证因此,不能使用/dog/endpoint
上的cat令牌进行身份验证,也不能使用/cat/endpoint
上的dog令牌进行身份认证。
我的想法/方法
a) 我理解,因为我有自定义的猫/狗过滤器,所以在创建bean时可以使用AuthenticationManagerResolver
并将一个实例传递到过滤器中。这个解析器可能看起来像
public AuthenticationManagerResolver<HttpServletRequest> resolver()
{
return request -> {
if (request.getPathInfo().startsWith("/dog/")) {
try {
return ???;
} catch (Exception exception) {
log.error(exception);
}
}
if (request.getPathInfo().startsWith("/cat/")) {
try {
return ???;
} catch (Exception exception) {
log.error(exception);
}
}
};
}
其中两个问题是:
公共空格配置(身份验证管理器生成器身份验证)
,但据我所知,我只会配置“一个”身份验证管理器,我可以在那里添加DogAP和CatAP,但这会让1个AM有2个AP,所以当使用此AM时,我可以在catendpoint上使用狗令牌进行身份验证b) 以某种方式实例化 2 个不同的身份验证管理器,然后使用安全配置将它们分配给不同的匹配器。
两个问题:
http.authorizeRequests()
.antMatchers("/dog/**")
.?
您可以发布多个筛选器链,也可以使用身份验证管理器解析程序
连接自己的身份验证筛选器
您可以使用< code > AuthenticationManagerResolver 返回不同的< code > AuthenticationManager 。从Spring Security 5.4.0开始,我们不再需要扩展< code > WebSecurityConfigurerAdapter 来配置我们的< code>SecurityFilterChain,您可以定义一个< code>SecurityFilterChain类型的bean。
我将详细介绍如何连接您自己的身份验证过滤器
。
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain apiSecurity(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((authz) -> authz
.anyRequest().authenticated());
http.addFilterBefore(apiAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
private AuthenticationFilter apiAuthenticationFilter() {
AuthenticationFilter authenticationFilter = new AuthenticationFilter(new ApiAuthenticationManagerResolver(), new BasicAuthenticationConverter());
authenticationFilter.setSuccessHandler((request, response, authentication) -> {});
return authenticationFilter;
}
public static class ApiAuthenticationManagerResolver implements AuthenticationManagerResolver<HttpServletRequest> {
private final Map<RequestMatcher, AuthenticationManager> managers = Map.of(
new AntPathRequestMatcher("/dog/**"), new DogAuthenticationProvider()::authenticate,
new AntPathRequestMatcher("/cat/**"), new CatAuthenticationProvider()::authenticate
);
@Override
public AuthenticationManager resolve(HttpServletRequest request) {
for (Map.Entry<RequestMatcher, AuthenticationManager> entry : managers.entrySet()) {
if (entry.getKey().matches(request)) {
return entry.getValue();
}
}
throw new IllegalArgumentException("Unable to resolve AuthenticationManager");
}
}
public static class DogAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
if (authentication.getName().endsWith("_dog")) {
return new UsernamePasswordAuthenticationToken(authentication.getName(), authentication.getCredentials(),
AuthorityUtils.createAuthorityList("ROLE_DOG"));
}
throw new BadCredentialsException("Username should end with _dog");
}
@Override
public boolean supports(Class<?> authentication) {
return true;
}
}
public static class CatAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
if (authentication.getName().endsWith("_cat")) {
return new UsernamePasswordAuthenticationToken(authentication.getName(), authentication.getCredentials(),
AuthorityUtils.createAuthorityList("ROLE_CAT"));
}
throw new BadCredentialsException("Username should end with _cat");
}
@Override
public boolean supports(Class<?> authentication) {
return true;
}
}
}
在上面的示例中,我们有两个身份验证提供者
,一个用于猫,另一个用于狗。它们是通过AntPath请求匹配器
解析的,该匹配器用于/狗/**
和/cat/*
endpoint,在ApiAuth
然后,将
ApiAut
您还可以为每个endpoint定义两个不同的过滤器链,如下所示:
@Bean
public SecurityFilterChain dogApiSecurity(HttpSecurity http) throws Exception {
http.requestMatchers((matchers) -> matchers
.antMatchers("/dog/**"));
http.authorizeRequests((authz) -> authz
.anyRequest().authenticated());
http.httpBasic();
http.authenticationProvider(new DogAuthenticationProvider());
return http.build();
}
@Bean
public SecurityFilterChain catApiSecurity(HttpSecurity http) throws Exception {
http.requestMatchers((matchers) -> matchers
.antMatchers("/cat/**"));
http.authorizeRequests((authz) -> authz
.anyRequest().authenticated());
http.httpBasic();
http.authenticationProvider(new CatAuthenticationProvider());
return http.build();
}
在定义多个过滤器链时,排序很重要,请在这些场景中使用
@Order
注释。
当你执行
http.requestMatcher(new AntPathRequestMatcher(“/endpoint/**”))时;
你告诉Spring Security只在请求与该路径匹配时才调用过滤器链。
Spring Security的存储库中还有一个票证,用于提供接受Map的
AuthenticationManagerResolver
实现。
我正在尝试使用http://localhost:3000/login?Id=1这样的查询参数来实现React路由器,我只能在我的登录路由中实现它,如果我将路径作为http://localhost:3000/然后重定向,但是,我想在整个应用程序中实现。如果我在其他路由上实现,它会匹配路由。这就是我的的样子,有人能指导我如何实现包括查询参数在内的所有路由路径吗?
我有一个XML文件,如下所示 我的XSL看起来像这样 然后,我尝试达到节点内元素的每个值 它没有显示值!我认为这是一种正确的方式。首先,我有for each select=“//警报,然后我有<代码> 请帮忙。
我正在尝试在我的URL中传递参数,但我的阅读有问题。我正在使用react-router v4。 网址:http://localhost:3000/reset?token=123我试着这样读: 但这打印空对象。奇怪的是,我试图将问号更改为其他字符,看起来它解决了我的问题,但我还是想保留问号。 网址:http://localhost:3000/reset_token=123 这已经工作了< code
在以下React应用程序中,有两个路由URLhttp://myapp 正确布线到布局构件。但是,URLhttp://myapp/login 也路由到布局组件,而不是登录。如果我将path=“/login”更改为“/sign”,它将正确路由到登录组件。 React路由器中的“/login”路径将其路由到路由是否有特殊之处?或者我设置这个路由的方式有错误吗?
问题内容: 我正在尝试使用单独的路线,但在我的React App中添加/编辑表单的组件相同,如下所示: 现在,在manageClient组件中,我解析查询参数(我在编辑路由中传递带有客户端ID的查询字符串),并根据传递的查询参数有条件地进行渲染。 问题在于这不会再次重新安装整个组件。假设打开了一个编辑页面,并且用户单击添加组件,URL发生了更改,但是该组件没有重新加载,因此保留在编辑页面上。 有办