相关疑难解决方法(0)

使用Spring Security进行单元测试

我的公司一直在评估Spring MVC,以确定我们是否应该在下一个项目中使用它.到目前为止,我喜欢我所看到的内容,现在我正在查看Spring Security模块,以确定它是否可以/应该使用.

我们的安全要求非常基本; 用户只需提供用户名和密码即可访问网站的某些部分(例如获取有关其帐户的信息); 并且网站上有一些页面(常见问题解答,支持等),应该授予匿名用户访问权限.

在我创建的原型中,我一直在Session中为经过身份验证的用户存储"LoginCredentials"对象(其中只包含用户名和密码); 例如,某些控制器检查此对象是否在会话中以获取对登录用户名的引用.我正在寻找用Spring Security取代这个本土逻辑,这将有很好的好处,可以删除任何类型的"我们如何跟踪登录用户?" 和"我们如何验证用户?" 来自我的控制器/业务代码.

似乎Spring Security提供了一个(每个线程)"上下文"对象,可以从应用程序的任何位置访问用户名/主体信息...

Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
Run Code Online (Sandbox Code Playgroud)

...在某种程度上,这个对象是一个(全局)单例,这似乎非常不像Spring.

我的问题是:如果这是在Spring Security中访问有关经过身份验证的用户的信息的标准方法,那么将Authentication对象注入SecurityContext的可接受方式是什么,以便在单元测试需要时可用于我的单元测试认证用户?

我是否需要在每个测试用例的初始化方法中进行连接?

protected void setUp() throws Exception {
    ...
    SecurityContextHolder.getContext().setAuthentication(
        new UsernamePasswordAuthenticationToken(testUser.getLogin(), testUser.getPassword()));
    ...
}
Run Code Online (Sandbox Code Playgroud)

这似乎过于冗长.有没有更简单的方法?

SecurityContextHolder物体本身似乎非常联合国春天般的...

java security spring unit-testing spring-security

131
推荐指数
6
解决办法
8万
查看次数

ReactiveSecurityContextHolder.getContext()为空,但@AuthenticationPrincipal有效

我一直在Spring Security + Webflux中使用ReactiveAuthenticationManager。它是经过自定义的,以返回一个实例UsernamePasswordAuthenticationToken,从该实例中我可以看出是调用时应接收的内容ReactiveSecurityContextHolder.getContext().map(ctx -> ctx.getAuthentication()).block()。据我所知,我无法通过两种方式访问​​身份验证上下文:

SecurityContextHolder.getContext().getAuthentication();
Run Code Online (Sandbox Code Playgroud)

要么

ReactiveSecurityContextHolder.getContext().map(ctx -> ctx.getAuthentication()).block()
Run Code Online (Sandbox Code Playgroud)

尝试从控制器或组件访问这些文件将解决null。对于我是否真的要Authentication在自定义管理器中返回实例,我有些怀疑,好像我是:

@Override
public Mono<Authentication> authenticate(final Authentication authentication) {
    if (authentication instanceof PreAuthentication) {
        return Mono.just(authentication)
            .publishOn(Schedulers.parallel())
            .switchIfEmpty(Mono.defer(this::throwCredentialError))
            .cast(PreAuthentication.class)
            .flatMap(this::authenticatePayload)
            .publishOn(Schedulers.parallel())
            .onErrorResume(e -> throwCredentialError())
            .map(userDetails -> new AuthenticationToken(userDetails, userDetails.getAuthorities()));
    }

    return Mono.empty();
}
Run Code Online (Sandbox Code Playgroud)

PreAuthentication的实例在哪里扩展AbstractAuthenticationTokenAuthenticationTokenUsernamePasswordAuthenticationToken

有趣的是,尽管ReactiveSecurityContextHolder.getContext().map(ctx -> ctx.getAuthentication()).block()在控制器中不起作用,但我可以@AuthenticationPrincipal在控制器中成功地将带有注释的身份验证主体作为方法参数注入。

这似乎是一个配置问题,但我不知道在哪里。有人知道为什么我不能返回身份验证吗?

java spring spring-security project-reactor spring-webflux

1
推荐指数
2
解决办法
1227
查看次数