如何为从 spring amqp 消息完成的事务建立安全上下文
how to establish security context for transactions done from spring amqp messages
我有一个 spring 引导应用程序,我使用 spring 安全注释为其保护方法,如下所示。
public interface UserService {
@PreAuthorize("hasRole('ADMIN')")
List<User> findAllUsers();
@PostAuthorize ("returnObject.type == authentication.name")
User findById(int id);
@PreAuthorize("hasRole('ADMIN')")
void updateUser(User user);
@PreAuthorize("hasRole('ADMIN') AND hasRole('DBA')")
void deleteUser(int id);
}
我在这里遇到的问题是,有些实现是通过 @RabbitListener
方法调用的,但没有任何安全上下文,因为它不是 Web 请求。
我希望客户端通过消息传递用户名 headers sp 我可以使用 message.getMessageProperties().getHeaders().get("username")
来获取该请求的用户名。
但我仍然相信不会有直接的方法,因为方法级注释不会被评估,因为它们不在安全上下文中。
有什么方法可以为 spring amqp 消息建立安全上下文吗?
只需添加上下文...
@SpringBootApplication
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class So49957413Application extends GlobalAuthenticationConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(So49957413Application.class, args);
}
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("foo").password("bar").roles("baz");
}
@Autowired
private Foo foo;
@RabbitListener(queues = "foo")
public void listen(Message in) {
try {
SecurityContext ctx = SecurityContextHolder.createEmptyContext();
ctx.setAuthentication(
new UsernamePasswordAuthenticationToken(in.getMessageProperties().getHeaders().get("user"), "bar"));
SecurityContextHolder.setContext(ctx);
this.foo.method1();
try {
this.foo.method2();
}
catch (AccessDeniedException e) {
System.out.println("Denied access to method2");
}
}
finally {
SecurityContextHolder.clearContext();
}
}
@Bean
public Foo foo() {
return new Foo();
}
public static class Foo {
@PreAuthorize("hasRole('baz')")
public void method1() {
System.out.println("in method1");
}
@PreAuthorize("hasRole('qux')")
public void method2() {
System.out.println("in method2");
}
}
}
和
in method1
Denied access to method2
最好在侦听器容器的通知链中 add/remove 通知中的安全上下文,以避免将安全代码与侦听器逻辑混合。
我有一个 spring 引导应用程序,我使用 spring 安全注释为其保护方法,如下所示。
public interface UserService {
@PreAuthorize("hasRole('ADMIN')")
List<User> findAllUsers();
@PostAuthorize ("returnObject.type == authentication.name")
User findById(int id);
@PreAuthorize("hasRole('ADMIN')")
void updateUser(User user);
@PreAuthorize("hasRole('ADMIN') AND hasRole('DBA')")
void deleteUser(int id);
}
我在这里遇到的问题是,有些实现是通过 @RabbitListener
方法调用的,但没有任何安全上下文,因为它不是 Web 请求。
我希望客户端通过消息传递用户名 headers sp 我可以使用 message.getMessageProperties().getHeaders().get("username")
来获取该请求的用户名。
但我仍然相信不会有直接的方法,因为方法级注释不会被评估,因为它们不在安全上下文中。
有什么方法可以为 spring amqp 消息建立安全上下文吗?
只需添加上下文...
@SpringBootApplication
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class So49957413Application extends GlobalAuthenticationConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(So49957413Application.class, args);
}
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("foo").password("bar").roles("baz");
}
@Autowired
private Foo foo;
@RabbitListener(queues = "foo")
public void listen(Message in) {
try {
SecurityContext ctx = SecurityContextHolder.createEmptyContext();
ctx.setAuthentication(
new UsernamePasswordAuthenticationToken(in.getMessageProperties().getHeaders().get("user"), "bar"));
SecurityContextHolder.setContext(ctx);
this.foo.method1();
try {
this.foo.method2();
}
catch (AccessDeniedException e) {
System.out.println("Denied access to method2");
}
}
finally {
SecurityContextHolder.clearContext();
}
}
@Bean
public Foo foo() {
return new Foo();
}
public static class Foo {
@PreAuthorize("hasRole('baz')")
public void method1() {
System.out.println("in method1");
}
@PreAuthorize("hasRole('qux')")
public void method2() {
System.out.println("in method2");
}
}
}
和
in method1
Denied access to method2
最好在侦听器容器的通知链中 add/remove 通知中的安全上下文,以避免将安全代码与侦听器逻辑混合。