JHipster 限制用户会话不适用于默认 JWT 配置
Posted
技术标签:
【中文标题】JHipster 限制用户会话不适用于默认 JWT 配置【英文标题】:JHipster limit user sessions not working with default JWT configuration 【发布时间】:2020-02-16 19:57:07 【问题描述】:我一直在查看许多类似的问题,但似乎没有任何效果。我在默认的 Jhispter 安全配置中添加了以下内容:
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.maximumSessions(1).maxSessionsPreventsLogin(true).sessionRegistry(sessionRegistry());
@Bean
public SessionRegistry sessionRegistry()
SessionRegistry sessionRegistry = new SessionRegistryImpl();
return sessionRegistry;
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher()
return new HttpSessionEventPublisher();
我知道 Spring Security 需要一个在下面添加的 HttpSessionListener,而且我看到关于是否需要添加 sessionRegistry 的相互矛盾的报告。
根据我在春季文档中阅读的所有内容,这应该足以将每个用户的登录次数限制为 1,但是您仍然可以无限次登录。 Jhispter 文档没有进入最大会话,因此也没有多大帮助。
这是整个安全配置:
package com.sean.silly.config;
import com.sean.silly.security.*;
import com.sean.silly.security.jwt.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter;
import org.springframework.security.web.session.HttpSessionEventPublisher;
import org.springframework.web.filter.CorsFilter;
import org.zalando.problem.spring.web.advice.security.SecurityProblemSupport;
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@Import(SecurityProblemSupport.class)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
private final TokenProvider tokenProvider;
private final CorsFilter corsFilter;
private final SecurityProblemSupport problemSupport;
public SecurityConfiguration(TokenProvider tokenProvider, CorsFilter corsFilter, SecurityProblemSupport problemSupport)
this.tokenProvider = tokenProvider;
this.corsFilter = corsFilter;
this.problemSupport = problemSupport;
@Bean
public PasswordEncoder passwordEncoder()
return new BCryptPasswordEncoder();
@Override
public void configure(WebSecurity web)
web.ignoring()
.antMatchers(HttpMethod.OPTIONS, "/**")
.antMatchers("/swagger-ui/index.html")
.antMatchers("/test/**");
@Override
public void configure(HttpSecurity http) throws Exception
// @formatter:off
http
.csrf()
.disable()
.addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
.exceptionHandling()
.authenticationEntryPoint(problemSupport)
.accessDeniedHandler(problemSupport)
.and()
.headers()
.contentSecurityPolicy("default-src 'self'; frame-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:")
.and()
.referrerPolicy(ReferrerPolicyHeaderWriter.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN)
.and()
.featurePolicy("geolocation 'none'; midi 'none'; sync-xhr 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; speaker 'none'; fullscreen 'self'; payment 'none'")
.and()
.frameOptions()
.deny()
.and()
.authorizeRequests()
.antMatchers("/api/authenticate").permitAll()
.antMatchers("/api/register").permitAll()
.antMatchers("/api/activate").permitAll()
.antMatchers("/api/account/reset-password/init").permitAll()
.antMatchers("/api/account/reset-password/finish").permitAll()
.antMatchers("/api/**").authenticated()
.antMatchers("/management/health").permitAll()
.antMatchers("/management/info").permitAll()
.antMatchers("/management/prometheus").permitAll()
.antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
.and()
.httpBasic()
.and()
.apply(securityConfigurerAdapter());
// @formatter:on
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.maximumSessions(1).maxSessionsPreventsLogin(true).sessionRegistry(sessionRegistry());
private JWTConfigurer securityConfigurerAdapter()
return new JWTConfigurer(tokenProvider);
@Bean
public SessionRegistry sessionRegistry()
SessionRegistry sessionRegistry = new SessionRegistryImpl();
return sessionRegistry;
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher()
return new HttpSessionEventPublisher();
【问题讨论】:
【参考方案1】:jhipster的security approach中JWT和Sessions(用于安全/登录)互斥(不可混用)
JWT 是一种无状态身份验证机制,因此防止或禁用多次登录需要额外的工作。看到类似问题here和here
配置会话不会对此产生影响。
此外,除了 JWT 问题,您的 http 会话配置在语法上是正确的,但在语义上似乎没有意义:
sessionCreationPolicy(SessionCreationPolicy.STATELESS)
说"spring will neither create nor use the http session" 实际上比您的用例的“从不”选项更错误。
因此,添加 maximumSessions(1)
(或其他任何内容)似乎没有任何意义。
【讨论】:
谢谢,没有点击 JWT 实现是 Sessions 独有的。你提供给我的链接有我想要的工作!以上是关于JHipster 限制用户会话不适用于默认 JWT 配置的主要内容,如果未能解决你的问题,请参考以下文章
扩展 Jhipster JWT (Spring) 单体应用程序以支持模拟