我创建了一个拦截器,向客户端发送的每个请求添加一个授权标头,这是代码:
import { HttpInterceptor, HttpRequest, HttpHandler, HttpHeaderResponse, HttpSentEvent, HttpProgressEvent, HttpResponse, HttpUserEvent, HttpEvent, HttpHeaders } from "@angular/common/http";
import { Observable } from "rxjs";
import { Injectable } from "@angular/core";
@Injectable()
export class AuthenticationInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.log(localStorage.getItem('jwtToken'));
if(localStorage.getItem('jwtToken')){
const request = req.clone({
setHeaders: {
Authorization: `bearer ${localStorage.getItem('jwtToken')}`
}
});
console.log(request.headers.get("Authorization"));
return next.handle(request);
}
return next.handle(req);
}
}
发送请求时,将调用函数拦截,并使用变量“ request”中的令牌值正确设置授权标头,如您所见: token console screenshot
但是授权标头没有出现在我的浏览器发送的请求中:network request headers,并且后端无法解析令牌。
你知道为什么吗?
这是我的弹簧配置:
WebSecurityConfig.java
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
public final static String AUTHORIZATION_HEADER = "Authorization";
@Autowired
UserService userService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(getProvider());
}
@Bean
public JwtTokenFilter jwtAuthenticationFilter() {
return new JwtTokenFilter();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/auth/**")
.permitAll()
.anyRequest()
.authenticated();
}
@Bean
public AuthenticationProvider getProvider() {
AppAuthProvider provider = new AppAuthProvider();
provider.setUserDetailsService(userService);
return provider;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
CorsConfig.java
@Configuration
public class CorsConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:4200")
.allowedMethods("*")
.allowedHeaders("*");
}
};
}
}
答案 0 :(得分:0)
您的问题出在后端服务中。出于安全原因,默认情况下仅接受某些标头,而其他标头将被忽略。
要解决您的问题,您需要设置自定义接受的标题。 Authorization
标头,即使就像JWT的标准一样,也被视为自定义标头。
我可以举一个我的Spring Security配置示例:
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("GET");
config.addAllowedMethod("POST");
config.addAllowedMethod("PUT");
config.addAllowedMethod("DELETE");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
注意该行
config.addAllowedHeader("*");
这意味着我的REST服务接受客户端发送的所有可能的标头。 显然,这不是一个很好的配置,应限制所允许的标头和其他内容以使其符合您的需求。
很明显,如果您不使用Spring Security,则需要找到使用您的语言/框架进行相同操作的方法。
这是我的SecurityConfig.java。与您的有点不同。 试试这个,让我知道
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private WLUserDetailsService userDetailsService;
@Value("${jwt.header}")
private String tokenHeader;
@Value("${jwt.route.authentication.path}")
private String authenticationPath;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoderBean());
}
@Bean
public PasswordEncoder passwordEncoderBean() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// we don't need CSRF because our token is invulnerable
.csrf().disable()
// TODO adjust CORS management
.cors().and()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// don't create session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("/auth/**").permitAll()
.anyRequest().authenticated();
// Custom JWT based security filter
JwtAuthorizationTokenFilter authenticationTokenFilter = new JwtAuthorizationTokenFilter(userDetailsService(), jwtTokenUtil, tokenHeader);
httpSecurity
.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
// // disable page caching
// httpSecurity
// .headers()
// .frameOptions().sameOrigin() // required to set for H2 else H2 Console will be blank.
// .cacheControl();
}
@Override
public void configure(WebSecurity web) {
// AuthenticationTokenFilter will ignore the below paths
web
.ignoring()
.antMatchers(
HttpMethod.POST,
authenticationPath
)
// allow anonymous resource requests
.and()
.ignoring()
.antMatchers(
HttpMethod.GET,
"/",
"/*.html",
"/favicon.ico",
"/**/*.html",
"/**/*.css",
"/**/*.js"
);
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
// config.addExposedHeader("Authorization, x-xsrf-token, Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, " +
// "Content-Type, Access-Control-Request-Method, Custom-Filter-Header");
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("GET");
config.addAllowedMethod("POST");
config.addAllowedMethod("PUT");
config.addAllowedMethod("DELETE");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}