haoxiaolan 2024-03-22 16:50 采纳率: 34.7%
浏览 13

spring Security不能问 openApi接口

springboot 使用了spring Security后 不能直接访问 openApi接口文档了

img

这段是我加的,但是没用





@Data
@Component
public class CheckTokenFilter extends OncePerRequestFilter {
    @Resource
    private JwtUtils jwtUtils;
    @Resource
    private CustomerUserDetailsService customerUserDetailsService;
    @Resource
    private LoginFailureHandler loginFailureHandler;
    @Resource
    private RedisService redisService;
    //获取登录请求地址
    @Value("${request.login.url}")
    private String loginUrl;
    @Value("${request.interface.url}")
    private String apiUrl;
    @Value("${request.ssoLogin.url}")
    private String ssoLoginUrl;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        try {
            //获取当前请求的url地址
            String url = request.getRequestURI();
            //如果当前请求不是登录请求或接口请求, 则需要进行token验证  || url.equals("/doc.html")
            if (!(url.equals(loginUrl) || url.equals(apiUrl) || url.equals(ssoLoginUrl) || url.equals("/doc.html")  )) {
                //进行token验证
                this.validateToken(request);
            }
        }catch (AuthenticationException e){
            loginFailureHandler.onAuthenticationFailure(request, response, e);
        }
        //登录请求不需要验证token
        doFilter(request, response, filterChain);
    }

    /**
     * 进行token验证
     * @param request
     * @throws AuthenticationException
     */
    private void validateToken(HttpServletRequest request) throws AuthenticationException {
        //从头部获取token信息
        String token = request.getHeader("token");
        //如果请求头部没有获取到token,则从请求的参数中进行获取
        if (ObjectUtils.isEmpty(token)) {
            token = request.getParameter("token");
        }
        //如果请求参数中也不存在token信息,则抛出异常
        if (ObjectUtils.isEmpty(token)) {
            throw new CustomerAuthenticationException("未经认证的非法访问!");
        }
        //判断redis中是否存在该token
        String tokenKey = "token_" + token;
        String redisToken = redisService.get(tokenKey);
        //如果redis里面没有token,说明该token失效
        if (ObjectUtils.isEmpty(redisToken)) {
            throw new CustomerAuthenticationException("会话超时,请重新登录!");
        }
        //如果token和Redis中的token不一致,则验证失败
        if (!token.equals(redisToken)) {
            throw new CustomerAuthenticationException("验证失败,请联系管理员!");
        }
        //如果存在token,则从token中解析出用户名
        String username = jwtUtils.getUsernameFromToken(token);
        //如果用户名为空,则解析失败
        if (ObjectUtils.isEmpty(username)) {
            throw new CustomerAuthenticationException("用户解析失败,请联系管理员!");
        }
        //获取用户信息
        UserDetails userDetails = customerUserDetailsService.loadUserByUsername(username);
        //判断用户信息是否为空
        if (userDetails == null) {
            throw new CustomerAuthenticationException("用户信息验证失败,请联系管理员!");
        }
        //创建身份验证对象
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        //设置到Spring Security上下文
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
    }
}




@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启权限注解控制
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    @Resource
    private CustomerUserDetailsService customerUserDetailsService;
    @Resource
    private LoginSuccessHandler loginSuccessHandler;
    @Resource
    private LoginFailureHandler loginFailureHandler;
    @Resource
    private AnonymousAuthenticationHandler anonymousAuthenticationHandler;
    @Resource
    private CustomerAccessDeniedHandler customerAccessDeniedHandler;
    @Resource
    private CheckTokenFilter checkTokenFilter;
    /**
     * 注入加密处理类
     * @return
     */
    @Bean
    public BCryptPasswordEncoderHandler passwordEncoder(){
        return new BCryptPasswordEncoderHandler();
    }

    /**
     * 处理登录认证
     * @param http
     * @throws Exception
     */
    protected void configure(HttpSecurity http) throws Exception {
        //登录前进行过滤
        http.addFilterBefore(checkTokenFilter, UsernamePasswordAuthenticationFilter.class);
        //表单登录
         http.formLogin()
                 //登录请求
                 .loginProcessingUrl("/user/login")
                 //设置登录用户名和密码,和默认一致就不用设置
                 //.usernameParameter("username")
                 //.passwordParameter("password")
                 //设置登录验证成功或失败后的的跳转地址
                 .successHandler(loginSuccessHandler)
                 .failureHandler(loginFailureHandler)
                 // 禁用csrf防御机制
                 .and().csrf().disable()
                 .sessionManagement()
                 //不创建Session
                 .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                 .and()
                 //设置需要拦截的请求
                 .authorizeRequests()
                 //不拦截登录请求
                 .antMatchers("/user/login")
                 .permitAll()
                 .antMatchers("/api/warn/*")
                 .permitAll()
                 .antMatchers("/api/login/*")
                 .permitAll()
                 // .antMatchers("/openapi/**", "/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html**", "/webjars/**")
                 // .permitAll()
                 //其它请求都需要拦截和身份认证
                 .anyRequest()
                 .authenticated()
                 .and()
                 .exceptionHandling()
                 //匿名无权限访问
                 .authenticationEntryPoint(anonymousAuthenticationHandler)
                 //认证用户无权限访问
                 .accessDeniedHandler(customerAccessDeniedHandler)
                 .and()
                 .cors();//开启跨域配置
    }
    /**
     * 配置认证处理器
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //密码加密
        auth.userDetailsService(customerUserDetailsService)
                .passwordEncoder(passwordEncoder());
    }


}

img

如何解决呀

  • 写回答

1条回答 默认 最新

  • 码农阿豪@新空间代码工作室 Java领域优质创作者 2024-03-22 16:50
    关注
    让阿豪来帮你解答,本回答参考chatgpt3.5编写提供,如果还有疑问可以评论或留言
    问题描述: springboot 使用了spring Security后 不能直接访问 openApi接口文档了。 解答: 在使用 Spring Security 的情况下,需要对接口请求进行身份认证和权限控制,因此不能直接访问 openApi 接口文档。需要配置 Spring Security 来放行特定的接口请求,以便能够访问 openApi 接口文档。 以下是一些可能的解决方案:
    1. 添加对 openApi 的放行规则 在 Spring Security 配置文件中添加如下代码:
    @Override    
    public void configure(WebSecurity web) throws Exception {        
        web.ignoring()                
            .antMatchers("/v2/api-docs", "/configuration/**", "/swagger*/**", "/webjars/**");    
    }
    

    以上代码将忽略对 "/v2/api-docs", "/configuration/", "/swagger*/", "/webjars/**" 的身份认证和权限控制。 2. 配置框架的资源路径 如果使用的是 Swagger 或 Swagger2,可以进行如下配置:

    @Configuration
    @EnableSwagger2
    public class SwaggerConfig {
        
        @Value("${swagger.show}")
        private boolean swaggerShow;
        @Bean
        public Docket createRestApi() {
            return new Docket(DocumentationType.SWAGGER_2)
                    .apiInfo(apiInfo())
                    .enable(swaggerShow)
                    .select()
                    .apis(RequestHandlerSelectors.basePackage("com.xxx.xxx.controller"))
                    .paths(PathSelectors.any())
                    .build();
        }
        private ApiInfo apiInfo() {
            return new ApiInfoBuilder()
                    .title("XXX接口")
                    .description("XXX接口文档")
                    .termsOfServiceUrl("https://github.com/")
                    .version("1.0")
                    .build();
        }
    }
    

    以上代码中通过配置 enable 属性来决定是否启用 Swagger,也可以在配置文件中进行配置。 3. 添加静态资源映射 在 Spring Boot 的配置文件中添加如下代码:

    spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
    

    以上代码将 Spring Boot 静态资源的访问路径映射到了多个目录下。如果 openApi 接口文档存在于这些目录之一,就可以直接访问了。 4. 修改 Spring Security 配置 在 Spring Security 配置文件中添加如下代码:

    .antMatchers("/doc.html").permitAll()
    

    以上代码将 "/doc.html" 这个页面放行,可以直接访问 openApi 接口文档。 代码示例:(方法 1 的示例)

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring()
                    .antMatchers("/v2/api-docs", "/configuration/**", "/swagger*/**", "/webjars/**");
        }
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            // ...
        }
    }
    
    评论

报告相同问题?

问题事件

  • 创建了问题 3月22日

悬赏问题

  • ¥15 mmo能不能做客户端怪物
  • ¥15 osm下载到arcgis出错
  • ¥15 Dell g15 每次打开eiq portal后3分钟内自动退出
  • ¥200 使用python编写程序,采用socket方式获取网页实时刷新的数据,能定时print()出来就行。
  • ¥15 matlab如何根据图片中的公式绘制e和v的曲线图
  • ¥15 我想用Python(Django)+Vue搭建一个用户登录界面,但是在运行npm run serve时报错了如何解决?
  • ¥15 QQ邮箱过期怎么恢复?
  • ¥15 登录他人的vue项目显示服务器错误
  • ¥15 (标签-android|关键词-app)
  • ¥15 comsol仿真压阻传感器