在 Spring Boot 中使用 jwt 令牌的具有 http 安全性的 CrossOrigin
Posted
技术标签:
【中文标题】在 Spring Boot 中使用 jwt 令牌的具有 http 安全性的 CrossOrigin【英文标题】:CrossOrigin with http security using jwt token in Spring boot 【发布时间】:2020-08-20 09:45:48 【问题描述】:我的 Spring Boot 应用程序中存在一些关于跨域和 http 安全性的问题。 当我在控制器类中使用 @crossorigin 注释方法时,我想使用 http 安全性。 但它没有接缝工作,即使该方法未使用@crosorigin,也始终会触发安全性。
有办法解决吗?
Jwtautoconfig 类:
@ManagementContextConfiguration
@ConditionalOnProperty(name = "af.security.active", havingValue = "true")
@Import(EnvironmentConfig.class, JwkRepository.class, JwtTokenUtil.class,
JwtAuthenticationProvider.class)
@EnableWebSecurity
@EnableConfigurationProperties(JwtSecurityProperties.class)
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@Order(Ordered.HIGHEST_PRECEDENCE)
public class JwtAutoConfig extends WebSecurityConfigurerAdapter
@Value("$af.security.jwt.white-list")
private String[] ignoredPaths;
@Value("$af.security.job-seeker-role:arbetssökande")
private String jobSeekerRole;
@Value("$af.security.officer-role:handläggare")
private String officer;
@Bean(name = "jwtauthenticationentrypoint")
public JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint()
return new JwtAuthenticationEntryPoint();
@Bean
public JwtSecurityHelper securityHelper()
return new JwtSecurityHelper(jobSeekerRole, officer);
@Bean
public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception
JwtAuthenticationTokenFilter authenticationTokenFilter = new JwtAuthenticationTokenFilter();
authenticationTokenFilter.setAuthenticationManager(authenticationManager());
authenticationTokenFilter.setAuthenticationSuccessHandler(new JwtAuthenticationSuccessHandler());
return authenticationTokenFilter;
@Override
public void configure(HttpSecurity http) throws Exception
http.requestMatchers()
.and()
.authorizeRequests()
.antMatchers("/**")
.authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf()
.disable();
// Custom JWT based security filter
http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
// disable page caching
http.headers().cacheControl();
@Override
public void configure(WebSecurity web)
final String[] trimmedIgnoredPaths = Stream.of(ignoredPaths)
.map(String::trim)
.toArray(String[]::new);
web.ignoring()
.antMatchers(HttpMethod.OPTIONS,"/**")
.and()
.ignoring().antMatchers(trimmedIgnoredPaths);
private Config hazelCastConfig()
Config config = new Config();
config.setInstanceName("app-cache")
.setNetworkConfig(new NetworkConfig()
.setJoin(new JoinConfig()
.setMulticastConfig(new MulticastConfig()
.setEnabled(false)
)
)
)
.addMapConfig(
new MapConfig()
.setName("object-cache")
.setMaxSizeConfig(new MaxSizeConfig(10, MaxSizeConfig.MaxSizePolicy.FREE_HEAP_SIZE))
.setEvictionPolicy(EvictionPolicy.LRU)
.setStatisticsEnabled(true)
.setTimeToLiveSeconds(14400));
return config;
@Bean(name="hazelcast")
public HazelcastInstance hazelcastInstance()
HazelcastInstance hazelcastInstance = new HazelcastInstanceFactory(hazelCastConfig()).getHazelcastInstance();
return hazelcastInstance;
CorsConfig 类:
@Configuration
public class CorsConfig
@Bean
public WebMvcConfigurer corsConfigurer()
return new WebMvcConfigurer()
@Override
public void addCorsMappings(CorsRegistry registry)
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", "DELETE", "GET" )
.allowCredentials(true);
;
这是我的控制器类中的方法:
@ApiOperation(value = "Hämtar alla frånvaron för en lista med användare")
@PostMapping(path= "/hamta-alla-franvaron", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<ExternalFranvaroDTO>> hamtaAllaFranvaron(
@ApiParam(value = "Identitet objekt som innehåller en lista av PISA_ID", required = true)
@Valid @RequestBody IdentitetForm identitet)
logger.info("MOTTAGET Rest-anrop (/hamta-alla-franvaron) Hamtar alla franvaron");
List<ExternalFranvaroDTO> externalFranvaroDTOLista = new ArrayList<>();
List<Franvaro> franvaron = franvaroService.hamtaAllaPagaendeOchNyaFriskskrivnaFranvaron(identitet.getPisaIds());
if(franvaron.isEmpty())
logger.debug("Inga pågende sjuk/vab anmälan");
return ResponseEntity.noContent().build();
franvaron.forEach( franvaro ->
ExternalFranvaroDTO externalFranvaroDTO = transformeraTillExternalFranvaroDTO(franvaro);
externalFranvaroDTOLista.add(externalFranvaroDTO);
);
return ResponseEntity.ok().body(externalFranvaroDTOLista);
现在我只想在使用 @crossorigin 时使用 http 安全
【问题讨论】:
为什么不直接在spring security中激活cross origin,然后在特定端点上配置spring security呢?还有为什么当spring security内置了一个自定义jwt过滤器时? docs.spring.io/spring-security/site/docs/current/reference/… 我该怎么做?我不确定如何在特定端点上配置 spring 安全性 【参考方案1】:我看不出你为什么要这样组合它。
您应该改为将安全性应用于特定端点并在 spring security 中配置 cors
过滤器,而不是像您所做的那样全局设置它。
如果您阅读 HttpSecurity 下的 spring 安全文档,您可以使用 antMatcher
并使用 ant syntax 匹配端点
protected void configure(HttpSecurity http) throws Exception
http
.authorizeRequests(authorize -> authorize
.antMatcher( // Here you can define endpoints using ant matching
"**/foo/**",
"**/bar/**"
)
.authenticated()
)
... // rest of configuration
你也可以使用 spring security 定义一个CORS filter
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
@Override
protected void configure(HttpSecurity http) throws Exception
http
// by default uses a Bean by the name of corsConfigurationSource
.cors(withDefaults())
...
@Bean
CorsConfigurationSource corsConfigurationSource()
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
您甚至可以激活和使用内置的jwt filter 并使用您自己的转换器等自定义过滤器。
protected void configure(HttpSecurity http)
http
.authorizeRequests(authorize -> authorize
.anyRequest().authenticated()
)
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
// or add a custom converter
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(jwt -> jwt
// adding a custom converter here
.jwtAuthenticationConverter(myConverter())
)
);
spring 安全文档真的非常非常好,您应该始终首先使用它作为信息来源。
【讨论】:
以上是关于在 Spring Boot 中使用 jwt 令牌的具有 http 安全性的 CrossOrigin的主要内容,如果未能解决你的问题,请参考以下文章
令牌 jwt 可与 spring boot 一起使用,但 angular 存在错误
在 Spring Boot 中使用 jwt 令牌的具有 http 安全性的 CrossOrigin
在spring boot微服务中设置JWT令牌生成中的两个主题