Spring security Spring安全性:按名称注销、锁定或禁用用户
我有一个使用spring security的测试应用程序,它有3个用户[suzy、frank、julie]。我的应用程序将事件发送到外部安全分析系统。该系统分析事件以确定它是否是“攻击”,然后应用程序轮询该系统以查看是否有任何事件被认为需要响应。下面是一个例子:Spring security Spring安全性:按名称注销、锁定或禁用用户,spring-security,Spring Security,我有一个使用spring security的测试应用程序,它有3个用户[suzy、frank、julie]。我的应用程序将事件发送到外部安全分析系统。该系统分析事件以确定它是否是“攻击”,然后应用程序轮询该系统以查看是否有任何事件被认为需要响应。下面是一个例子: bob执行操作1(已发送事件) bob执行(错误)2(已发送事件) bob执行操作3(已发送事件) 应用程序轮询外部系统并发现bob现在应该注销 鲍勃注销(怎么注销?) bob的下一个请求被重定向到登录页面 请注意: 外部分析系统正在
- 外部分析系统正在检查spring security不会检查的东西(想想欺诈分析之类的东西)
- “轮询”检查本质上是一个后台线程,因此它不会阻止请求
loadUserByUsername("bob").disable();
我现在希望构建的功能只是:
- 注销
- 禁用
loadByUsername(“bob”).logout()
)。但我不知道如何执行帐户禁用
如果可能的话,我希望不必构建核心API的定制实现。我希望这是任何使用spring security的人都可以轻松集成此功能的地方。我将把它分解为两个问题: 以编程方式注销用户 不幸的是,如果不以某种方式扩展核心API,我认为没有办法做到这一点。幸运的是,与核心API的集成相当简单 我概述了几种方法,因为我不确定“背景方法”是否提供了很多优势(稍后将对此进行详细介绍) 自定义SecurityContextRepository 在这个时候,我认为这是最好的办法 后台线程方法(根据请求)是有意义的,这样在向应用程序发出请求时就不必阻塞。但是,如果没有一些共享数据存储,您就无法轻松地与另一个线程通信(更不用说集群环境实例中另一台计算机上的另一个进程了) Spring Security获取当前用户的方式是使用
SecurityContextRepository
实现。默认实现从HttpSession
获取用户。您可以这样做:
GET /j_spring_security_logout HTTP/1.1
Host: www.example.org
Cookie: JSESSIONID=<some-id>;
公共类SecurityAnalyzerSecurityContextRepository
实现SecurityContextRepository{
专用最终安全分析器SecurityAnalyzer;
私人最终证券内容临时代表;
public SecurityAnalyzer SecurityContextExtrepository(SecurityAnalyzer SecurityAnalyzer){
这(securityAnalyzer,新的HttpSessionSecurityContextRepository());
}
public SecurityAnalyzer SecurityContextRepository(SecurityAnalyzer SecurityAnalyzer,SecurityContextRepository委托){
this.securityAnalyzer=securityAnalyzer;
this.delegate=委托;
}
公共安全上下文加载上下文(HttpRequestResponseHolder请求响应Holder){
SecurityContext上下文=delegate.loadContext(requestResponseHolder);
Authentication=context.getAuthentication();
if(身份验证==null){
返回上下文;
}
String principal=authentication.getName();
//您的SecurityAnalyzer实现需要实现isEvil
if(securityAnalyzer.isEvil(委托人)){
返回SecurityContextHolder.createEmptyContext();
}
返回上下文;
}
public void saveContext(SecurityContext上下文、HttpServletRequest请求、,
HttpServletResponse(响应){
saveContext(上下文、请求、响应);
}
公共布尔containsContext(HttpServletRequest){
返回delegate.containsContext(请求);
}
}
其思想是,您可以委托给现有的SecurityContextRepository
,并验证用户是否被确定为邪恶
或者,您可以提供一个SecurityContextRepository
实现,该实现从后台线程可以写入的存储加载。无论哪种方式,尽管有一个对商店的阻塞呼叫
背景线程方法
注意:我认为这不是正确的方法,因此这个答案没有那么详细
第一步是编写轮询外部系统的后台任务。显然,Spring Security无法提供此步骤,因为它不知道如何与外部系统交互
此操作的代码可能类似于:
SecurityAnalyzer=。。。
Set evillusernames=analyzer.getandremovenewevillusernames();
... 如何处理用户名。。。
现在的问题是如何处理这些用户名。默认情况下,Spring Security将从HttpSession
获取当前用户。大多数Servlet容器默认将HttpSession
实现持久化为内存中的Map
。Spring Security无法获取对此映射的引用
直接使用JSESSIONID
一种选择是,如果我们能够获得每个用户的JSESSIONID,我们可以发出如下请求:
GET /j_spring_security_logout HTTP/1.1
Host: www.example.org
Cookie: JSESSIONID=<some-id>;
然后使用响应,您可以使用令牌发布帖子:
POST /logout HTTP/1.1
Host: www.example.org
Cookie: JSESSIONID=<some-id>;
_csrf=<csrf-token>
POST/logout HTTP/1.1
主持人:www.example.org
Cookie:JSESSIONID=;
_csrf=
此时您可能会问,但我如何知道JSESSIONID?一种选择是使用Spring Security的。但是,开箱即用的实现不适用于集群实现