Spring Boot 仅当用户经过身份验证时才允许端点

ltskdhd1  于 12个月前  发布在  Spring
关注(0)|答案(2)|浏览(124)

我尝试使用Angular向我的Sping Boot 应用程序发送GET请求。为了进行身份验证,我将token传递给header:

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor() {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    const token = getCookieValue('token');

    if (token) {
      const authRequest = request.clone({
        setHeaders: {
          Authorization: `Bearer ${token}`
        }
      });
      return next.handle(authRequest);
    }
    return next.handle(request);
  }
}

字符串
浏览器显示此错误:
CORS策略已阻止从源“http://localhost:4200”访问位于“http://localhost:8080/api/user-profile/get-data”的XMLHttpRequest:对预检请求的响应未通过访问控制检查:请求的资源上不存在“Check-Control-Allow-Origin”标头。
这是我在Sping Boot 中的配置:

public class SecurityConfiguration implements WebMvcConfigurer {
    private final JwtFilter jwtFilter;
    private final DataSource dataSource;

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:4200")
                .allowedMethods("*");
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf(AbstractHttpConfigurer::disable);

        http.sessionManagement(sess -> sess.sessionAuthenticationStrategy(sessionAuthenticationStrategy()));

        http.authorizeHttpRequests(auth ->
                auth
                        .requestMatchers("/", "/api/auth/oauth").authenticated() // also tried with "/api/user-profile/**"
                        .requestMatchers("/", "/api/auth/**").permitAll()
                        .anyRequest().authenticated()
        );

        http.httpBasic(withDefaults());
        http.oauth2Login(withDefaults());
        http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }


这就是我如何发送请求并防止CORS错误:
发送基本请求(不带令牌):

this.http.get(environment.apiBaseUrl + 'user-profile/get-data').subscribe(result => {
  console.log(result);
})


在Sping Boot 中,将.requestMatchers("/", "/api/auth/**").permitAll()替换为.requestMatchers("/", "/api/auth/**", "/api/user-profile/**").permitAll()
现在我没有收到错误消息,但我可以在没有经过身份验证的情况下发送请求,这不是我的目标。
这是我尝试读取token的方式:

@AllArgsConstructor
@Component
public class JwtFilter extends OncePerRequestFilter {
    private final CustomUserService customUserService;
    private Jwt jwt;

    @Override
    protected void doFilterInternal(HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull FilterChain filterChain) throws ServletException, IOException {
        final String authorizationHeader = request.getHeader("Authorization");
        String token = null;
        String username = null;

        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            token = authorizationHeader.substring(7);
            // Check if token is valid
            try {
                jwt.isTokenValid(token, customUserService.loadUserByUsername(jwt.extractUsername(token)));
            }
            catch (Exception e) {
                Response responseObj = Response.builder()
                        .code("UNAUTHORIZED")
                        .status(HttpStatus.UNAUTHORIZED)
                        .timestamp(LocalDateTime.now())
                        .messages(Collections.singletonList("Invalid token"))
                        .build();
                ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());
                String json = mapper.writeValueAsString(responseObj);
                response.setContentType("application/json");
                response.setCharacterEncoding("UTF-8");
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                response.getWriter().write(json);
                return;
            }
            username = jwt.extractUsername(token);
        }

        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = customUserService.loadUserByUsername(username);

            if (jwt.isTokenValid(token, userDetails)) {
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }
        filterChain.doFilter(request, response);
    }
}


我不知道我做错了什么,但authorizationHeader总是null

lztngnrs

lztngnrs1#

在我的情况下,我不得不写以下代码到我的.htaccess文件,以防止CORS错误:

# Always set these headers.
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, 
origin, authorization, accept, client-security-token"
Header always set Access-Control-Expose-Headers: "authorization"

字符串
要更改或创建.htaccess文件,您需要访问服务器的文件系统。

gab6jxml

gab6jxml2#

我是这样解决这个问题的:
在Angular中,我在src中创建了proxy.conf.json文件。

{
  "/api": {
    "target": "http://localhost:8080",
    "pathRewrite": {
      "^/api": "/api/"
    },
    "secure": false,
    "changeOrigin": true
  }
}

字符串
angular.json中,我将以下内容添加到"serve": {

"options": {
  "browserTarget": "angl:build",
  "proxyConfig": "src/proxy.conf.json"
},


package.json中,我将"start": "ng serve",替换为"start": "ng serve --proxy-config src/proxy.conf.json",
问题解决了,它完全符合我的要求。在Spring Boot 中没有任何变化。

相关问题