为每个端点 Spring MVC 指定不同的(基本)身份验证登录
Posted
技术标签:
【中文标题】为每个端点 Spring MVC 指定不同的(基本)身份验证登录【英文标题】:Specify different (basic) authentication log-in per endpoint Spring MVC 【发布时间】:2022-01-09 21:42:50 【问题描述】:想象以下(假设的)数据结构
endpoint | username | password
users admin 123
info george awd
data magnus e4
这意味着每个端点都需要不同的凭据,并且没有一个用户名/密码组合可以登录到每个端点。在添加更多端点时,我正在寻找一种在我们的 Spring MVC 项目中使其可扩展的方法。我们可以使用角色并将其硬核到配置类中,但端点和登录组合因每个客户安装而异
鉴于以下 SecurityConfiguration 和 LookupAuthenticationService 是在数据库中查找用户名/密码数据的类
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
private static final String[] ENDPOINT_LIST =
"/rest/**"
;
@Override
protected void configure(HttpSecurity http) throws Exception
http
.authorizeRequests()
.antMatchers(ENDPOINT_LIST)
.authenticated()
.and()
.httpBasic();
@Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
auth.authenticationProvider(authenticationProvider());
@Bean
public DaoAuthenticationProvider authenticationProvider()
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService());
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
@Bean
public PasswordEncoder passwordEncoder()
return new BCryptPasswordEncoder();
@Override
protected UserDetailsService userDetailsService()
return new LookupAuthenticationService(passwordEncoder());
理想的情况是 LookupAuthenticationService 可以访问请求,因此我们知道要获取哪个端点,但我想这只有在使用单个过滤器时才有可能
目前我发现的可能性是:
为每个端点添加一个 WebSecurityConfigurerAdapter 和多个特定的 UserDetailsServer -> 大量代码 为每个端点添加一个 HandlerInterceptor -> 大量代码 AuthenticationManagerResolver 根据 pathInfo 返回不同的 AuthenticationManager?任何关于如何最好地解决此问题的意见将不胜感激
【问题讨论】:
endpoint 只是一个权限,只是添加规则,用于 url 映射和权限。 1 个配置已解决。 你能详细说明一下这个@M.Deinum 吗? 您可以编写一个用户查询,将endpoint
列映射到用户的权限/角色。然后,您可以为给定权限添加 url/endpoints 的安全性。
【参考方案1】:
您可以有一个表,您可以在其中将端点映射到规则,如下所示:
pattern | authority |
---|---|
/users/** | ROLE_ADMIN |
/info/** | ROLE_USER |
/another/** | ROLE_ANOTHER |
您无需将用户分配给端点,而是将角色分配给用户。有了这个,您可以创建一个AuthorizationManager
,它将根据请求路径保护您的端点。
@Component
public class AccessRuleAuthorizationManager implements AuthorizationManager<RequestAuthorizationContext>
private final AccessRuleRepository rules;
private RequestMatcherDelegatingAuthorizationManager delegate;
public AccessRuleAuthorizationManager(AccessRuleRepository rules)
this.rules = rules;
@Override
public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext object)
return this.delegate.check(authentication, object.getRequest());
@EventListener
void applyRules(ApplicationReadyEvent event)
Builder builder = builder();
for (AccessRule rule : this.rules.findAll())
builder.add(
new AntPathRequestMatcher(rule.getPattern()),
AuthorityAuthorizationManager.hasAuthority(rule.getAuthority())
);
this.delegate = builder.build();
而且,在您的 SecurityConfiguration
中,您只需执行以下操作:
@Autowired
private AccessRuleAuthorizationManager access;
@Override
protected void configure(HttpSecurity http) throws Exception
http
.authorizeHttpRequests((authz) ->
authz.anyRequest().access(this.access)
)
.httpBasic(Customizer.withDefaults());
我建议您查看this repository 并观看存储库描述中的演示文稿。演示文稿的最后一步是添加自定义 AuthorizationManager
,对此有很好的解释。
【讨论】:
感谢您的广泛回复,它帮助我深入了解我真正想问的问题。我可能会删除这个问题,因为它没有多大意义。不幸的是,在我们的系统中,用户不是传统用户,可以使用相同的用户名但使用不同的密码定义多个用户 - 不允许我为单个用户设置角色。我需要一种更即时的方式来处理 UserDetailsService/loadUserByUsername 不允许的事情以上是关于为每个端点 Spring MVC 指定不同的(基本)身份验证登录的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot之执行器端点(Actuator Endpoint)实现剖析
Spring Security + MVC:相同的@RequestMapping,不同的@Secured
如何正确计时用 Java Spring MVC 编写的 API?