Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring boot 仅在需要身份验证时应用spring安全筛选器(由我的应用程序)_Spring Boot_Spring Security - Fatal编程技术网

Spring boot 仅在需要身份验证时应用spring安全筛选器(由我的应用程序)

Spring boot 仅在需要身份验证时应用spring安全筛选器(由我的应用程序),spring-boot,spring-security,Spring Boot,Spring Security,我读过,这似乎是最接近我的问题,但没有充分回答它 下面您将看到我当前使用的WebSecurity配置适配器配置。它不会一直保持这样,因为我以后不会公开h2控制台 我的问题是,JwtAuthenticationFilter总是被执行。我更希望在需要身份验证的请求上执行过滤器(在我的特定情况下:仅此处所述: .authorizeRequests() .anyRequest() .authenticated() ) 如何做到这一

我读过,这似乎是最接近我的问题,但没有充分回答它

下面您将看到我当前使用的WebSecurity配置适配器配置。它不会一直保持这样,因为我以后不会公开h2控制台

我的问题是,
JwtAuthenticationFilter
总是被执行。我更希望在需要身份验证的请求上执行过滤器(在我的特定情况下:仅此处所述:

.authorizeRequests()
                .anyRequest()
                    .authenticated()
)

如何做到这一点

注意:我的应用程序登录正常工作,而H2控制台也正常工作,但一直抛出
io.jsonwebtoken.SignatureException
,因为JWT H2控制台生成和使用的与我的应用程序使用的不同

Web安全配置适配器:

编辑:这是JwtAuthenticationFilter。如果你也需要TOs,请告诉我

JwtAuthenticationFilter:

package com.particles.authservice.jwt;
导入java.io.IOException;
导入java.util.Optional;
导入javax.servlet.FilterChain;
导入javax.servlet.ServletException;
导入javax.servlet.http.HttpServletRequest;
导入javax.servlet.http.HttpServletResponse;
导入org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
导入org.springframework.security.core.context.SecurityContextHolder;
导入org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
导入org.springframework.util.StringUtils;
导入org.springframework.web.filter.OncePerRequestFilter;
导入com.particles.authservice.tos.UserJwt;
公共类JwtAuthenticationFilter扩展了OncePerRequestFilter{
私有静态最终字符串授权\u头\u前缀=“授权”;
私有静态最终字符串授权\u头\u承载\u前缀=“承载”;
私有静态最终整数授权\头\承载\前缀\长度=授权\头\承载\前缀.LENGTH();
@自动连线
私人JwtService JwtService;
@凌驾
受保护的无效doFilterInternal(最终HttpServletRequest请求、最终HttpServletResponse响应、最终FilterChain FilterChain)
抛出ServletException、IOException{
if(request.getHeader(AUTHORIZATION\u HEADER\u PREFIX)!=null){
最终可选选项optoken=extractTokenFromRequest(请求);
if(optoken.isPresent()&&StringUtils.hasText(optoken.get())&&jwtService.isTokenValid(optoken.get()){
//如果令牌存在且有效,则检索相应的UserJwt对象
最终用户jwt jwt=jwtService.getJwtFromToken(optoken.get());
final UsernamePasswordAuthenticationToken authenticationToken=新UsernamePasswordAuthenticationToken(jwt.getUser(),null,
jwt.getUser().getAuthorities());
setDetails(新的WebAuthenticationDetailsSource().buildDetails(请求));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
}
filterChain.doFilter(请求、响应);
}
/**
*此方法从{@link HttpServletRequest}-对象中提取JWT。
*
*@param请求
*({@link-HttpServletRequest})请求,它应该包含一个JWT
*@return(OptionalString)JWT作为字符串
*/
私有可选extractTokenFromRequest(最终HttpServletRequest请求){
最终字符串bearerToken=request.getHeader(授权\头\前缀);
字符串bearerTokenContent=null;
if(StringUtils.hasText(bearerToken)和&bearerToken.startsWith(授权\头\承载\前缀)){
bearerTokenContent=bearerToken.substring(授权\头\承载\前缀\长度,bearerToken.LENGTH());
}
返回可选的空值(BealerTokenContent);
}
}

如果您需要查看任何其他类,请告诉我,我将在此处粘贴它们。

添加以下方法以公开您的公共端点

 @Override
 public void configure(WebSecurity web) throws Exception {
    web.ignoring()
    .antMatchers("/public-api/**");
  }

似乎不可能仅使用
WebSecurityConfigurerAdapter#configure
方法将筛选器应用于特定端点

相反,我决定将私有API中的端点与所有其他端点分开

  • 需要过滤器的端点(在我的例子中是
    JwtAuthenticationFilter
    )在
    /api/
    下收集,并且没有单独定义,因为很有可能有人忘记将它们添加到
    configure
    -方法中
  • 所有其他端点的路径与
    /api/
我的配置方法如下所示:

@Override
    protected void configure(final HttpSecurity http) throws Exception {
        //@formatter:off
        http
            .cors()
                .and()
            .csrf()
                .disable()
            .headers()
                .frameOptions()
                    .disable()
                    .and()
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
            .authorizeRequests()
                .antMatchers("/",
                        "/favicon.ico",
                        "/**/*.png",
                        "/**/*.gif",
                        "/**/*.svg",
                        "/**/*.jpg",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js")
                    .permitAll()
                .antMatchers("/h2-console/**").permitAll()
                .antMatchers(HttpMethod.POST,
                        PUBLIC_API_PATH + "register",
                        PUBLIC_API_PATH + "login")
                    .permitAll()
                .antMatchers(HttpMethod.GET,
                        PUBLIC_API_PATH + "confirm")
                    .permitAll()
                .and()
            .authorizeRequests()
                .anyRequest()
                    .authenticated()
                .and()
            .exceptionHandling()
                .authenticationEntryPoint(unauthorizedHandler)
                .accessDeniedHandler(unauthorizedHandler)
                .and()
            .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
            ;
        //@formatter:on
JwtAuthenticationFilter
中,我检查请求路径是否包含私有API路径
/API/
。我只应用过滤,如果它这样做

    @Override
    protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain)
            throws ServletException, IOException {
        if (request.getRequestURI().contains(SecurityConfiguration.PRIVATE_API_PATH)) {
            // perform Jwt-authentication since request-URI suggests a call to private-API
...
            }
        }

        filterChain.doFilter(request, response);
    }
我不喜欢这个解决方案,特别是因为我必须保持
SecurityConfiguration.PRIVATE\u API\u PATH
一个常量,因为@map(value)需要一个常量。不过,它完成了任务

如果你有更好的建议,我很想试试

编辑
显然,可以在@*映射(value)中使用如下变量:
@PostMapping(value=“${apipath}/user”)
。因此,我毕竟可以使路径可配置-但是签入
JwtAuthenticationFilter
必须保持不变;我不需要使用常量,而是使用变量,这些变量包含来自例如
application.yaml

的值,我完全愿意这样做,但目前我的API在
localhost:9191/auth/*
下,h2控制台也是如此(
localhost:9191/auth/h2控制台
)。我是否应该尝试重新调整,使我的所有公共端点都位于
localhost:9191/auth/publicapi
下,而私有API则位于
localhost:9191/auth/publicapi>下<
@Override
    protected void configure(final HttpSecurity http) throws Exception {
        //@formatter:off
        http
            .cors()
                .and()
            .csrf()
                .disable()
            .headers()
                .frameOptions()
                    .disable()
                    .and()
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
            .authorizeRequests()
                .antMatchers("/",
                        "/favicon.ico",
                        "/**/*.png",
                        "/**/*.gif",
                        "/**/*.svg",
                        "/**/*.jpg",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js")
                    .permitAll()
                .antMatchers("/h2-console/**").permitAll()
                .antMatchers(HttpMethod.POST,
                        PUBLIC_API_PATH + "register",
                        PUBLIC_API_PATH + "login")
                    .permitAll()
                .antMatchers(HttpMethod.GET,
                        PUBLIC_API_PATH + "confirm")
                    .permitAll()
                .and()
            .authorizeRequests()
                .anyRequest()
                    .authenticated()
                .and()
            .exceptionHandling()
                .authenticationEntryPoint(unauthorizedHandler)
                .accessDeniedHandler(unauthorizedHandler)
                .and()
            .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
            ;
        //@formatter:on
    @Override
    protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain)
            throws ServletException, IOException {
        if (request.getRequestURI().contains(SecurityConfiguration.PRIVATE_API_PATH)) {
            // perform Jwt-authentication since request-URI suggests a call to private-API
...
            }
        }

        filterChain.doFilter(request, response);
    }