我正在寻找一种方法来实现我的Spring应用程序的维护模式。
当应用程序处于维护模式时,仅允许用户role = MAINTENANCE
登录。其他所有人都将被重定向到登录页面。
现在我刚刚建立了一个过滤器:
@Component
public class MaintenanceFilter extends GenericFilterBean {
@Autowired SettingStore settings;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if(settingStore.get(MaintenanceMode.KEY).isEnabled()) {
HttpServletResponse res = (HttpServletResponse) response;
res.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
} else {
chain.doFilter(request, response);
}
}
}
并使用以下内容添加它:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// omitted other stuff
.addFilterAfter(maintenanceFilter, SwitchUserFilter.class);
}
因为就我所知,SwitchUserFilter
应该是Spring Security过滤器链中的最后一个过滤器。
现在每个请求都会被取消,并得到一个503响应,尽管没有办法访问登录页面。
如果我添加一个重定向到过滤器,这将导致一个无限循环,因为访问登录页也被拒绝。
另外,我找不到一个很好的方法来获得当前用户的角色。或者我应该只使用SecurityContextHolder
?
我正在寻找一种方法来重定向每个用户到登录页面(也许与查询参数?maintenance=true
),每个用户与role = MAINTENANCE
可以使用该应用程序。
因此,过滤器/拦截器的行为应类似于:
if(maintenance.isEnabled()) {
if(currentUser.hasRole(MAINTENANCE)) {
// this filter does nothing
} else {
redirectTo(loginPage?maintenance=true);
}
}
3条答案
按热度按时间xmd2e60i1#
我现在找到了两个类似的解决方案,但我注入代码的地方看起来不太好。
对于这两种情况,我都添加了一个自定义的
RequestMatcher
,它获取的@Autowired
并检查是否启用了维护模式。解决方案1:
在我的安全配置中:
解决方案2:
非常相似,但使用
HttpServletRequest.isUserInRole(...)
:如果启用了维护模式并且当前用户没有
MY_ROLE
,则将执行denyAll()
。唯一的缺点是,我不能设置一个自定义的响应。我更喜欢返回一个
503 Service Unavailable
。也许有人能想出如何做到这一点。9fkzdhlc2#
这有点像是先有鸡还是先有蛋的两难问题,您希望向未授权用户显示“我们处于维护模式...”消息,同时允许授权用户登录,但您不知道他们是否已获得授权,直到他们登录。理想情况下,将此设置在某种筛选器中会很好,但我发现在实践中,通过将逻辑放在登录之后,对我来说解决类似问题会更容易。就像在
UserDetailsService
中一样。下面是我在一个项目中解决这个问题的方法。当我处于维护模式时,我为视图设置了一个标志,在全局标题或登录页面中显示“我们处于维护模式..”消息。这样,无论用户是谁,都知道这是维护模式。登录应该正常工作。
在用户通过身份验证后,在我的自定义
UserDetailsService
中,用户的详细信息将与他们的角色一起加载,我将执行以下操作:它并不漂亮,但它很容易理解(我认为这对安全配置很好),而且它很有效。
更新:
使用您的解决方案,我必须销毁每个人的会话,否则在启用维护模式之前登录的用户仍然可以使用系统
在我们的项目中,我们不允许任何用户在维护模式下登录。一个管理员启动一个任务,启用“维护...”msg,并进行倒计时,然后在最后,我们使用
SessionRegistry
终止每个人的会话。rjjhvcjd3#
我也是类似的情况,发现这个答案很有帮助。我遵循了第二种方法,也设法返回自定义响应。
下面是我为返回自定义响应所做的工作。
1-定义一个返回所需自定义响应的控制器方法。
2-在您的安全上下文中,您应该允许访问此URL。
3-创建自定义拒绝访问异常处理程序
4-在安全配置中注册自定义访问拒绝异常处理程序