活动介绍

package com.os.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { // 设置允许跨域的路径 registry.addMapping("/**") // 设置允许跨域请求的域名 .allowedOriginPatterns("*") // 是否允许cookie .allowCredentials(true) // 设置允许的请求方式 .allowedMethods("GET", "POST", "DELETE", "PUT") // 设置允许的header属性 .allowedHeaders("*") // 跨域允许时间 .maxAge(3600); } } package com.os.config; import com.os.filter.JwtAuthenticationFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.Customizer; 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.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import javax.annotation.Resource; @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Resource private JwtAuthenticationFilter jwtAuthenticationFilter; @Resource private AuthenticationEntryPoint authenticationEntryPoint; @Resource private AccessDeniedHandler accessDeniedHandler; @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .cors().and() //开启跨域 .authorizeRequests() .antMatchers("/user/user/login", "/user/user/register", "/user/user/retrievePassword", "/common/sendVerificationCode", "/common/sendRetrievePasswordCode").anonymous() .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() .anyRequest().authenticated() .and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); //添加过滤器 http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); //配置异常处理 http.exceptionHandling() .authenticationEntryPoint(authenticationEntryPoint) .accessDeniedHandler(accessDeniedHandler); } @Bean public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } } 这是我的跨域配置和security配置,为什么不能正确进行跨域请求

时间: 2025-06-13 19:18:58 浏览: 31
<think>嗯,用户提供了两个Java配置类,分别是跨域配置和Spring Security配置,但遇到了跨域请求无法正常工作的问题。我需要仔细分析可能的原因。 首先看CorsConfig类。它实现了WebMvcConfigurer,并重写了addCorsMappings方法。这里允许所有路径的跨域,使用allowedOriginPatterns("*"),同时允许凭证(allowCredentials(true))。不过,我记得当使用allowCredentials(true)时,不能使用allowedOrigins("*"),因为浏览器出于安全考虑不允许同时使用通配符和凭证。虽然用户这里用的是allowedOriginPatterns,可能需要检查Spring版本是否支持这种写法。allowedOriginPatterns是在Spring 5.3之后引入的,支持更灵活的模式匹配,但即使这样,当允许凭证时,是否允许使用通配符? 接下来是SecurityConfig类,继承自WebSecurityConfigurerAdapter。在configure方法中,调用了.cors().and(),这应该是启用了Spring Security的CORS支持。但问题可能出在这里:如果CorsConfig已经配置了全局CORS,但Spring Security的CORS配置可能需要单独处理。有时候,即使全局CORS配置正确,Spring Security的过滤器链可能会覆盖这些设置,导致跨域请求被拦截。特别是对于需要认证的请求,Spring Security可能会优先处理,这时候需要确保CORS配置被正确应用到Security过滤器链中。 另外,用户可能没有将CorsConfig正确注册为一个Bean,或者在Spring Security的配置中没有正确启用CORS。虽然用户已经使用了@Configuration注解,应该会被扫描到,但可能需要确认是否存在多个CORS配置冲突的情况。 再检查HTTP方法,用户配置了allowedMethods包括GET、POST、DELETE、PUT,但可能遗漏了OPTIONS方法。不过,在SecurityConfig中,用户特别允许了所有OPTIONS请求的预检(preflight)请求,即.antMatchers(HttpMethod.OPTIONS, "/**").permitAll(),这应该处理了OPTIONS请求的问题。但跨域预检请求需要正确响应,可能还需要CORS配置中的allowedMethods包含OPTIONS方法,或者在Security配置中确保OPTIONS请求不被拦截。 还有一个可能性是,当浏览器发起跨域请求时,如果携带了认证信息(比如JWT token),而服务器返回的响应头中没有正确的Access-Control-Allow-Origin,或者通配符被拒绝。这时候即使配置了allowedOriginPatterns("*"),当allowCredentials为true时,可能需要具体指定允许的来源,而不是使用通配符。比如,应该设置具体的域名,如allowedOriginPatterns("https://example.com"),而不是"*"。 另外,检查Security的配置中是否关闭了csrf,这里已经调用了http.csrf().disable(),是正确的,因为跨域请求容易受到CSRF攻击,但禁用后可以减少配置复杂度。 总结可能的问题点: 1. allowedOriginPatterns("*")与allowCredentials(true)同时存在,导致浏览器拒绝请求。 2. Spring Security的CORS配置没有正确使用全局CORS配置,需要确认是否在Security中正确启用。 3. 预检请求的处理可能存在问题,虽然配置了OPTIONS放行,但CORS配置中的allowedMethods是否包含OPTIONS? 可能的解决方案: 1. 将allowedOriginPatterns("*")替换为具体的域名,或使用allowedOriginPatterns,但可能需要处理凭证的问题。 2. 检查Spring版本是否支持allowedOriginPatterns,并确认其与allowCredentials的兼容性。 3. 确保Spring Security的CORS配置引用了全局的CORS配置,或者在Security配置中显式配置CORS。</think>你的跨域配置存在几个关键问题,需要按以下步骤调整: --- ### 一、**CORS 配置冲突分析** #### 1. **`allowedOriginPatterns("*")` 与 `allowCredentials(true)` 不兼容** - **问题**:当启用凭证(`allowCredentials(true)`)时,浏览器禁止使用通配符 `*` 作为 `allowedOrigins`。需明确指定允许的域名。 - **解决**:替换为具体域名或动态匹配: ```java .allowedOriginPatterns("http://localhost:8080", "https://yourdomain.com") // 或动态匹配(需确保安全) .allowedOriginPatterns("http://*.example.com") ``` #### 2. **未包含 `OPTIONS` 方法** - **问题**:预检请求(Preflight)会使用 `OPTIONS` 方法,但你的配置仅允许 `GET, POST, DELETE, PUT`。 - **解决**:在 `allowedMethods` 中添加 `OPTIONS`: ```java .allowedMethods("GET", "POST", "DELETE", "PUT", "OPTIONS") ``` --- ### 二、**Spring Security 配置调整** #### 1. **显式启用全局 CORS 配置** - **问题**:Spring Security 默认会覆盖全局 CORS 配置。 - **解决**:在 `SecurityConfig` 中通过 `cors(Customizer.withDefaults())` 强制使用全局配置: ```java http .csrf().disable() .cors(Customizer.withDefaults()) // 启用全局 CORS .authorizeRequests() ... ``` #### 2. **确保 `OPTIONS` 请求放行** - 你的配置已正确放行 `OPTIONS` 请求,无需修改: ```java .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() ``` --- ### 三、**完整修正后的代码** #### 1. **跨域配置(CorsConfig.java)** ```java @Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOriginPatterns("http://localhost:*", "https://yourdomain.com") // 按需替换域名 .allowCredentials(true) .allowedMethods("GET", "POST", "DELETE", "PUT", "OPTIONS") .allowedHeaders("*") .maxAge(3600); } } ``` #### 2. **安全配置(SecurityConfig.java)** ```java @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .cors(Customizer.withDefaults()) // 关键调整:强制使用全局 CORS .authorizeRequests() .antMatchers("/user/user/login", "/user/user/register").anonymous() .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() .anyRequest().authenticated() .and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // 其他配置(过滤器、异常处理)保持不变 } } ``` --- ### 四、**验证步骤** 1. **检查浏览器控制台报错**:查看是否存在 `CORS policy` 相关错误。 2. **使用 Postman 或 curl 测试**:确认预检请求(OPTIONS)返回正确的 `Access-Control-Allow-*` 头。 3. **验证凭证传递**:确保请求头包含 `Authorization` 时,响应头包含 `Access-Control-Allow-Credentials: true`。 通过以上调整,跨域问题应被解决。如果仍有异常,请提供具体错误信息以便进一步排查。
阅读全文

相关推荐

package com.lx.config; import com.alibaba.druid.pool.DruidDataSource; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; public class jdbcConfig { @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; @Bean public DataSource dataSource(){ DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(driver); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); return dataSource; } @Bean public PlatformTransactionManager transactionManager(DataSource dataSource){ DataSourceTransactionManager ds = new DataSourceTransactionManager(); ds.setDataSource(dataSource); return ds; } } package com.lx.config; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.context.annotation.Bean; import javax.sql.DataSource; public class MybatisConfig { @Bean public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){ SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSource); factoryBean.setTypeAliasesPackage("com.lx.domain"); return factoryBean; } @Bean public MapperScannerConfigurer mapperScannerConfigurer(){ MapperScannerConfigurer msc = new MapperScannerConfigurer(); //接口 msc.setBasePackage("com.lx.dao"); return msc; } } package com.lx.config; import org.springframework.web.filter.CharacterEncodingFilter; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; import java.util.logging.Filter; public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer { protected Class<?>[] getRootConfigClasses() { return new Class[]{SpringConfig.class}; } protected Class<?>[] getServletConfigClasses() { return new Class[]{SpringmvcConfig.class}; } protected String[] getServletMappings() { return new String[]{"/"}; } /*protected Filter[] getServletFilters(){ CharacterEncodingFilter filter = new CharacterEncodingFilter(); filter.setEncoding("UTF-8"); return new Filter[]{filter}; }*/ }package com.lx.config; import org.springframework.web.filter.CharacterEncodingFilter; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; import java.util.logging.Filter; public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer { protected Class<?>[] getRootConfigClasses() { return new Class[]{SpringConfig.class}; } protected Class<?>[] getServletConfigClasses() { return new Class[]{SpringmvcConfig.class}; } protected String[] getServletMappings() { return new String[]{"/"}; } /*protected Filter[] getServletFilters(){ CharacterEncodingFilter filter = new CharacterEncodingFilter(); filter.setEncoding("UTF-8"); return new Filter[]{filter}; }*/ } package com.lx.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.PropertySource; import org.springframework.transaction.annotation.EnableTransactionManagement; @Configuration @ComponentScan({"com.lx.service"}) @PropertySource("jdbc.properties") @Import({jdbcConfig.class , MybatisConfig.class}) @EnableTransactionManagement public class SpringConfig { } package com.lx.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; @Configuration @ComponentScan("com.lx.controller") @EnableWebMvc public class SpringmvcConfig { } 对以上五个整合ssm的配置类结合javaweb的几层框架做出解释,并总结一下不同配置类之间的关系作用

package com.hw.camunda.config.filter; import com.hw.camunda.config.SecurityProperties; import com.hw.camunda.exception.BaseException; import com.hw.camunda.exception.ErrorMsg; import com.hw.camunda.service.impl.CustomUserDetailsService; import com.hw.camunda.utils.JwtUtil; import jakarta.annotation.Resource; import jakarta.servlet.*; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.annotation.Order; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; @Order(1) @Component public class TokenFilter extends OncePerRequestFilter { private final CustomUserDetailsService userDetailsService; private final SecurityProperties securityProperties; @Autowired public TokenFilter(SecurityProperties securityProperties,CustomUserDetailsService userDetailsService) { this.securityProperties = securityProperties; this.userDetailsService = userDetailsService; } // 允许的过期后刷新时间(分钟) private static final int ALLOW_EXPIRED_MINUTES = 10; @Override public boolean shouldNotFilter(HttpServletRequest request) { String uri = request.getRequestURI(); return securityProperties.getPermitUrls().contains(uri); } @Override public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { // 从请求头中获取token String token = request.getHeader("Authorization"); if (token == null || token.isEmpty()) { throw new BaseException(ErrorMsg.JWT_TOKEN_INVALID); } // 去掉可能的"Bearer "前缀 if (token.startsWith("Bearer ")) { token = token.substring(7); } try { // 先尝试验证token(未过期的情况) JwtUtil.validateToken(token); } catch (BaseException e) { // 如果捕获到过期异常,我们尝试刷新 if (e.getErrorCode().toString().equals(ErrorMsg.LOGIN_TOKEN_EXPIRE.getCode()+"")) { // 尝试刷新令牌 try { token = JwtUtil.refreshToken(token, ALLOW_EXPIRED_MINUTES); // 将新令牌设置到响应头,客户端需要保存并替换旧令牌 response.setHeader("New-Access-Token", token); } catch (BaseException ex) { // 刷新失败,抛出异常(可能是过期时间超过10分钟或无效token) throw ex; } } else { // 其他验证失败的情况(如无效token) throw e; } } //最好保存到redis中 UserDetails userDetails = userDetailsService.loadUserByUsername(token); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authenticationToken); chain.doFilter(request, response); } } package com.hw.camunda.exception; import com.hw.camunda.utils.JsonResult; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.security.access.AccessDeniedException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.NoHandlerFoundException; import org.springframework.web.servlet.resource.NoResourceFoundException; import javax.security.sasl.AuthenticationException; @ControllerAdvice @ResponseBody @Order(Ordered.HIGHEST_PRECEDENCE) public class ExceptionHandlerAdvice { @ExceptionHandler(BaseException.class) @ResponseBody public JsonResult<String> baseException(BaseException e){ if (e.getErrorCode() != null) { return JsonResult.error(e.getErrorCode(),e.getMessage()); }else { return JsonResult.error(e.getMessage()); } } @ExceptionHandler(NoResourceFoundException.class) @ResponseBody public JsonResult<String> resourceFound(NoResourceFoundException ex) { return JsonResult.error(ErrorMsg.NOT_PERMISSION); } @ExceptionHandler(NoHandlerFoundException.class) @ResponseBody public JsonResult<String> handleFound(NoHandlerFoundException ex) { return JsonResult.error(ErrorMsg.NOT_PERMISSION); } @ExceptionHandler(AccessDeniedException.class) @ResponseBody public JsonResult<String> handleAccessDenied(AccessDeniedException ex) { return JsonResult.error(ErrorMsg.NOT_PERMISSION); } // 处理认证失败异常 @ExceptionHandler(AuthenticationException.class) @ResponseBody public JsonResult<String> handleAuthFailure(AuthenticationException ex) { return JsonResult.error(ErrorMsg.NOT_LOGIN); } @ExceptionHandler(value = RuntimeException.class) @ResponseBody public JsonResult<String> runtimeException(RuntimeException e){ return JsonResult.error("业务异常:"+e.getMessage()); } @ExceptionHandler(value = Exception.class) @ResponseBody public JsonResult<String> allException(Exception e){ e.printStackTrace(); return JsonResult.error("系统异常:"+e.getMessage()); } } 为什么返回的是500package com.hw.camunda.config; import com.hw.camunda.config.filter.TokenFilter; import com.hw.camunda.service.impl.CustomUserDetailsService; import jakarta.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; @Configuration @EnableWebSecurity @EnableMethodSecurity // 启用方法级注解鉴权 public class SecurityConfig { private final CustomUserDetailsService userDetailsService; private final SecurityProperties securityProperties; @Autowired public SecurityConfig(SecurityProperties securityProperties,CustomUserDetailsService userDetailsService) { this.securityProperties = securityProperties; this.userDetailsService = userDetailsService; } /** * 安全过滤链配置 - 清晰定义拦截规则 * 优先级:从上到下匹配规则 */ @Bean SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(AbstractHttpConfigurer::disable) .addFilterBefore(new TokenFilter(securityProperties,userDetailsService), UsernamePasswordAuthenticationFilter.class); /*.authorizeHttpRequests(auth -> { for (String permitUrl : securityProperties.getPermitUrls()) { auth.requestMatchers(permitUrl).permitAll(); } auth.requestMatchers("/api/**").authenticated() .anyRequest().denyAll(); } );*/ return http.build(); } }

package com.kuafu.login.config; import com.kuafu.login.handle.AuthenticationEntryPointImpl; import com.kuafu.login.handle.JwtAuthenticationTokenFilter; import com.kuafu.login.handle.LogoutSuccessHandlerImpl; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 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.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.firewall.HttpFirewall; import org.springframework.security.web.firewall.StrictHttpFirewall; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.mvc.method.RequestMappingInfo; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import java.util.Map; @Slf4j @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) @ConditionalOnProperty(prefix = "login", name = "enable") public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private ApplicationContext applicationContext; /** * 认证失败处理类 */ @Autowired private AuthenticationEntryPointImpl unauthorizedHandler; @Autowired private LogoutSuccessHandlerImpl logoutSuccessHandler; /** * token认证过滤器 */ @Autowired private JwtAuthenticationTokenFilter authenticationTokenFilter; @Autowired private RequestMappingHandlerMapping requestMappingHandlerMapping; @Override protected void configure(HttpSecurity http) throws Exception { final Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMappingHandlerMapping.getHandlerMethods(); ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http .cors().and() .csrf().disable() // 禁用HTTP响应标头 .headers().cacheControl().disable().and() // 认证失败处理类 .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() .authorizeRequests(); registry .antMatchers("/doc.html").permitAll() .antMatchers("/login/**").permitAll() .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js","/profile/**").permitAll() .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll() .antMatchers("/**/*.png","/**/*.jpg","/**/*.svg","/**/*.ico").permitAll() .antMatchers("/").permitAll(); handlerMethods.forEach((info, method) -> { registry.antMatchers(info.getPatternsCondition().getPatterns().toArray(new String[0])).authenticated(); }); registry.and().headers().frameOptions().disable(); // 添加Logout filter http.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler); // 添加JWT filter http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } /** * 身份认证接口 */ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { Map<String, AuthenticationProvider> providerMap = applicationContext.getBeansOfType(AuthenticationProvider.class); for (Map.Entry<String, AuthenticationProvider> entry : providerMap.entrySet()) { log.info("=============== loading provider {}", entry.getKey()); auth.authenticationProvider(entry.getValue()); } } @Bean public HttpFirewall allowDoubleSlashFirewall() { StrictHttpFirewall firewall = new StrictHttpFirewall(); firewall.setAllowUrlEncodedDoubleSlash(true); return firewall; } }

最新推荐

recommend-type

基于Go封装的openblas.zip

基于Go封装的openblas.zip
recommend-type

python39-winrm-0.4.3-1.el8.tar.gz

# 适用操作系统:Centos8 #Step1、解压 tar -zxvf xxx.el8.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm
recommend-type

qgis-server-3.18.3-3.el8.tar.gz

# 适用操作系统:Centos8 #Step1、解压 tar -zxvf xxx.el8.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm
recommend-type

起点中文网 go 客户端,基于网页版页面提取。.zip

起点中文网 go 客户端,基于网页版页面提取。.zip
recommend-type

精品推荐-2025数据治理实践峰会(脱敏)PPT合集.zip

2025数据治理实践峰会(脱敏)PPT合集,供大家参考与学习。 一、面向Data+AI的数据治理范式跃迁 1、领域xAI驱动AI时代的数据治理范式跃迁 2、治理即服务:腾讯游戏数据治理的AI范式跃迁 3、AI治理与伦理:前沿探索与实践落地 二、数据治理的坑点与方法论总结 1、降本增效,智启未来:央国企Data+Al 数据治理实践与探索 2、中小银行数据治理探索与实践 三、数据治理最佳实践 1、京东零售数据中台:熵增时代下一体化数据治理体系 四、元数据与数据血缘 1、AllData数据中台集成开源项目OpenMetadata破局工业数据孤岛 2、Apache Gravitino:统一元数据之统一血缘
recommend-type

11款开源中文分词引擎性能对比分析

在当今信息时代,中文分词作为自然语言处理中的一个基础且关键环节,对于中文信息检索、机器翻译、语音识别等领域的应用至关重要。分词准确度直接影响了后续的语言分析与理解。由于中文不同于英文等西方语言,中文书写是以连续的字符序列来表达,不存在明显的单词间分隔符,如空格。因此,在处理中文文本之前,必须先进行分词处理,即确定字符串中的词边界。 开放中文分词引擎是指那些提供免费使用的中文文本分词服务的软件。在开放源代码或提供分词API的分词系统上,开发者和研究者可以测试和评估它们在不同场景和数据集上的性能,以便选择最适合特定需求的分词引擎。 本文件标题为“11款开放中文分词引擎测试数据”,意味着内容涉及11个不同的中文分词引擎。这些引擎可能覆盖了从传统基于规则的方法到现代基于机器学习和深度学习的方法,也可能包括了针对特定领域(如医疗、法律等)优化的分词引擎。以下将对这些分词引擎的重要知识点进行详细阐述。 1. 基于规则的分词引擎:这类引擎依据汉语语法规则和词典进行分词。词典会包含大量的词汇、成语、习惯用语等,而规则会涉及汉语构词方式、歧义消解等。优点在于分词速度快,对常见文本的处理效果好;缺点是规则和词典需要不断更新,对新词和专业术语的支持不足。 2. 基于统计的分词引擎:通过大规模的语料库进行训练,统计各个词语的出现概率,从而实现分词。这种方法能够自动学习和适应新词和新用法,但需要的计算资源较大。 3. 基于深度学习的分词引擎:利用深度神经网络模型,如循环神经网络(RNN)和卷积神经网络(CNN),来识别和分词。近年来,基于Transformer架构的预训练模型,如BERT和GPT,也开始被应用到中文分词任务中,具有更好的语境理解和处理能力。 4. 评估指标:通常使用准确率(precision)、召回率(recall)和F1分数作为分词效果的评价指标。准确率是指分词结果中正确词占所有识别词的比例,召回率是指分词结果中正确词占实际正确词的比例,F1分数是准确率和召回率的调和平均。 5. 测试数据集:测试数据集通常由不同类型的文本组成,如新闻、科技文献、社交媒体文本等,用于评估分词引擎在不同场景下的性能。测试数据集的多样性和丰富度是影响分词引擎性能评估的关键。 6. 性能对比:通过对比各款分词引擎在相同测试数据集上的表现,可以分析出哪些分词引擎在准确率、速度、资源消耗等方面表现更优,哪些更适合处理特定类型的文本。 7. 应用场景:分词引擎的选择也依赖于其应用场景。例如,搜索引擎可能更重视速度和准确率,而语音识别则可能更注重实时性和对口语的适应性。 8. 开源分词引擎:一些开源分词引擎如HanLP、结巴分词(Jieba)等,提供了丰富的功能和社区支持,同时便于开发者根据特定需求进行定制和优化。 通过上述内容,我们可以看到中文分词引擎的重要性和测试数据的作用。开发者和研究人员可以根据测试结果,选择适合自己应用需求的分词工具,并且对分词引擎的性能进行优化,进一步提高中文信息处理的质量和效率。
recommend-type

【大规模EEG数据处理技巧】:EEGbdfreader性能优化秘籍

# 摘要 本文综合探讨了大规模EEG数据处理的关键理论和技术实践,重点介绍了一个名为EEGbdfreader的工具及其在数据处理中的应用。文中首先概述了大规模EEG数据处理的挑战,随后深入介绍了EEGbdfreader工具的安装、配置、基本操作和高级功能,包括
recommend-type

安卓studio多行注释快捷键

<think>好的,我现在需要帮助用户查找Android Studio中多行注释的快捷键。首先,我得回想一下自己之前对Android Studio的了解。通常,不同的IDE有不同的注释快捷键,比如Eclipse中使用Ctrl + /,而IntelliJ IDEA系列(包括Android Studio)可能使用类似的快捷方式。不过用户提到的问题可能涉及到特定情况下的快捷键冲突,比如引用[2]中提到的Kotlin方法注释快捷键的问题,这说明用户可能遇到了快捷键不生效的情况,需要检查是否有冲突。 接下来,我应该确认标准的Android Studio多行注释快捷键是什么。根据常规知识,Windows
recommend-type

JavaFX自学资料整理合集

JavaFX是一个由Oracle公司开发的用于构建富客户端应用程序的软件平台。它是Java SE的一个部分,能够帮助开发者创建图形用户界面(GUI)应用程序,这类应用程序具备现代桌面应用的特性,例如多媒体、图形和动画。JavaFX是Java的一个补充,它利用了Java的强大功能,同时提供了更加丰富的组件库和更加灵活的用户界面布局功能。 在自学整理JavaFX的过程中,以下是一些重要的知识点和概念: 1. JavaFX的架构和组件 JavaFX拥有一个模块化的架构,它由多个组件构成,包括JavaFX Scene Builder、JavaFX运行时、JavaFX SDK、NetBeans IDE插件等。JavaFX Scene Builder是一个可视化工具,用于设计UI布局。JavaFX SDK提供了JavaFX库和工具,而NetBeans IDE插件则为NetBeans用户提供了一体化的JavaFX开发环境。 2. JavaFX中的场景图(Scene Graph) 场景图是JavaFX中用于定义和管理用户界面元素的核心概念。它由节点(Nodes)组成,每个节点代表了界面中的一个元素,如形状、文本、图像、按钮等。节点之间可以存在父子关系,形成层次结构,通过这种方式可以组织复杂的用户界面。 3. FXML FXML是一种XML语言,它允许开发者以声明的方式描述用户界面。使用FXML,开发者可以将界面布局从代码中分离出来,使界面设计可以由设计师独立于程序逻辑进行处理。FXML与JavaFX Scene Builder结合使用可以提高开发效率。 4. JavaFX中的事件处理 JavaFX提供了强大的事件处理模型,使得响应用户交互变得简单。事件处理涉及事件监听器的注册、事件触发以及事件传递机制。JavaFX中的事件可以是键盘事件、鼠标事件、焦点事件等。 5. JavaFX的动画与媒体API JavaFX支持创建平滑的动画效果,并且能够处理视频和音频媒体。动画可以通过时间线(Timeline)和关键帧(KeyFrame)来实现。JavaFX媒体API提供了丰富的类和接口,用于控制音视频的播放、暂停、停止、调整音量等。 6. CSS与JavaFX CSS样式表可以用于美化JavaFX应用程序界面,提供与Web开发中相似的样式设置能力。JavaFX应用了大部分CSS 3标准,允许开发者使用CSS来控制节点的样式,比如颜色、字体、边框等。 7. JavaFX的过渡效果和效果库 JavaFX拥有内置的过渡效果库,可以为节点提供多种动画效果,如移动、旋转、缩放和淡入淡出等。除此之外,JavaFX还提供了一系列的效果,如阴影效果、反射效果、模糊效果等,可以应用于节点以增强视觉表现。 8. JavaFX的数据绑定 数据绑定是JavaFX中非常重要的一个特性,它允许开发者将用户界面元素与后端数据源连接起来。数据绑定可以简化代码的编写,减少手动同步数据的需要。 9. JavaFX的模块化 JavaFX的模块化特性使其可以轻松集成到Java应用中,并且可以独立于Java核心库进行下载和更新,这样有利于JavaFX的快速迭代和减少应用体积。 10. JavaFX的多种输入设备支持 JavaFX支持多种输入设备,包括鼠标、键盘、触摸板等。它提供了一套完整的API来处理各种输入设备的事件,使得创建交互式的用户体验成为可能。 了解这些知识点之后,JavaFX的自学和资料整理工作会更加有条理和系统。由于这些内容较为广泛,因此在实际学习过程中,重点应该是逐一深入理解每一个概念,并尝试在实践项目中应用这些知识点。通过编写小程序和应用来实际感受JavaFX的开发流程和操作细节,最终达到熟练掌握的目的。
recommend-type

【MATLAB编程优化术】:针对EEGbdfreader的代码调优策略

# 摘要 EEGbdfreader作为一款处理脑电图(EEG)数据的软件工具,在临床和研究领域有着广泛应用。本文首先介绍了EEGbdfreader的基本功能和面临的性能挑战,随后回顾了MATLAB编程的基础知识,为深入理解软件内部机制和后续优化工作奠定了基础。第三章重点探讨了EEGbdfreader的代码优化策略,包括代码重构、内存管理、数据缓存以及并行计算与多线程的应用,旨在提升程序性能和效率。第四章则深入讲解