我在Springboot中有这个应用程序作为后端,而angular应用程序作为前端,我的问题是,当我从angular向后端执行http get调用时,它会用
'从源' http://localhost:4200 '访问位于' http://localhost:8080/operator/getall '的XMLHttpRequest已被CORS策略阻止:对印前检查请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。
为了更好地理解,这里有一些拦截器的后端和前端项目的图片以及所有安全配置的东西。
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfiguration {
private final JwtAuthenticationFilter jwtAuthenticationFilter;
private final UserService userService;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable)
.cors(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(request -> request.requestMatchers("/auth/**")
.permitAll().requestMatchers("/operator/**").hasAnyRole("ADMIN").anyRequest().authenticated())
.sessionManagement(manager -> manager.sessionCreationPolicy(STATELESS))
.authenticationProvider(authenticationProvider()).addFilterBefore(
jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userService.userDetailService());
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config)
throws Exception {
return config.getAuthenticationManager();
}
}
@RestController
@RequestMapping(path = "/operator")
@CrossOrigin(origins = "http://localhost:4200/", maxAge = 3600)
@RequiredArgsConstructor
@PreAuthorize("hasRole('ADMIN')")
public class OperatoreController {
@Autowired
private OperatoreService operatoreService;
@GetMapping(path = "/getall")
public ResponseEntity<List<Operatore>> getAllOperatore(){
return ResponseEntity.ok(operatoreService.getAll());
}
}
@RestController
@RequestMapping(path = "/auth")
@CrossOrigin(origins = "http://localhost:4200", maxAge = 3600)
@RequiredArgsConstructor
public class AuthenticationController {
@Autowired
private OperatoreService operatoreService;
@Autowired
private final AuthenticationServiceImpl authenticationService;
@PostMapping("/login")
public ResponseEntity<JwtAuthenticationResponse> Login(@RequestBody LoginRequest request) {
return ResponseEntity.ok(authenticationService.signin(request));
}
}
执行调用的前端服务
@Injectable({
providedIn: 'root'
})
export class HomeService {
constructor(private http: HttpClient) { }
getAll() {
console.log(`${environment.apiUrl}/${environment.servizi.api.getAll}`)
return this.http.get(`${environment.apiUrl}/${environment.servizi.api.getAll}`)
}
}
拦截器
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(private authenticationService: AuthService) {}
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
// add authorization header with jwt token if available
const currentUser = this.authenticationService.currentUserValue;
if (currentUser && currentUser.token) {
console.log("SEEET token "+ currentUser.token)
/**request = request.clone({
headers: request.headers.append("Authorization",`Bearer ${currentUser.token}`)
});**/
request = request.clone({
setHeaders: {
Authorization: `Bearer ${currentUser.token}`
},
});
}
return next.handle(request);
}
}
更奇怪的是,只有在OperatoreController getall中的那个方法上返回这个错误,身份验证工作,它按预期返回jwt
!(https://i.stack.imgur.com/wzBXk.png)
还试穿了 Postman 的衣服
!(https://i.stack.imgur.com/xsM7B.png)
JwtAuthentication Filter
@Component
@AllArgsConstructor public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtServiceImpl jwtService;
private final TokenRepository tokenRepository;
private final UserDetail userService;
@Override
protected void doFilterInternal(@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response, @NonNull FilterChain filterChain)
throws ServletException, IOException {
final String authHeader = request.getHeader("Authorization");
final String jwt;
final String userEmail;
if (StringUtils.isEmpty(authHeader) || !StringUtils.startsWith(authHeader, "Bearer ")) {
filterChain.doFilter(request, response);
return;
}
jwt = authHeader.substring(7);
userEmail = jwtService.extractUserName(jwt);
if (StringUtils.isNotEmpty(userEmail)
&& SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userService.userDetailService()
.loadUserByUsername(userEmail);
var isTokenValid = tokenRepository.findByToken(jwt)
.map(t -> !t.isExpired() && !t.isRevoked())
.orElse(false);
if (jwtService.isTokenValid(jwt, userDetails) && isTokenValid && userDetails.isEnabled()) {
SecurityContext context = SecurityContextHolder.createEmptyContext();
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
context.setAuthentication(authToken);
SecurityContextHolder.setContext(context);
}
}
filterChain.doFilter(request, response);
}
}
编辑1
经过一些修改,我做了我的代码,我发现Angular提出了一个OPTIONS请求,但要访问/operator/getAll中的请求方法,它必须经过身份验证,所以我的JwtAuthenticationFilter丢弃了它,然后CorsError appers,事实上,如果我们试图将方法移动到不需要JWT接受请求的AuthenticationController中,
但是我不能添加jwt到CORS策略的OPTIONS请求,我希望访问OperatorController请求必须经过身份验证,所以我不知道如何解决这个问题,有人能帮助我吗
1条答案
按热度按时间deikduxw1#
您需要设置代理配置才能使其工作。我怀疑你尝试的是不正确的,也许?
对于生产,你需要配置你的服务器从相同的URL服务的应用程序,或编排你的应用程序与反向代理等。
为了让开发服务器工作,你可以使用Angular CLI的内置代理。
https://angular.io/guide/build#proxying-to-a-backend-server
1.创建
proxy.conf.json
(the pathRewrite由你决定,我相信你现在不需要,但明智的做法是为后端调用提供一个url段)
1.在
projects/<your projectname>/architect/serve
下将此添加到angular.json
:现在
ng serve
应该可以工作了。