San*_*ama 2 java interceptor http-headers spring-boot angular
在我的演示应用程序中,我遇到一个问题,即我没有收到从 Angular 客户端添加到 Spring boot 服务器的请求标头。作为安全措施,我有 SSL(安全套接字层)和 CORS(跨源资源共享)配置。在我的应用程序中,CSRF(跨站点请求伪造)被禁用。我使用 JWT(JSON Wen Token)作为每个请求的用户身份验证机制。这就是我需要从标头中提取 JWT 密钥的地方。我将从我的应用程序中添加代码示例,请帮助我找出问题。
\n角拦截器
\nimport { Injectable } from \'@angular/core\';\nimport { HttpEvent, HttpInterceptor, HttpResponse, HttpHandler, HttpRequest, HttpHeaders } from \'@angular/common/http\'; \nimport { UserService } from \'./user.service\';\nimport { Observable } from \'rxjs\';\n\n/*Interceptor\n Often you\xe2\x80\x99ll want to intercept HTTP requests or responses before they\xe2\x80\x99re handled else where in the application*/ \n\n@Injectable({\n providedIn: \'root\'\n})\nexport class InterceptorService implements HttpInterceptor {\n\n /**\n * Constructor of InterceptorService. \n * @param userService UserService\n */\n constructor(private userService: UserService) { }\n\n /**\n * Responsible for intercepting requests. \n * Responsible for adding \'Authorization\' header with JWT (Json Web Token). \n * @param theRequest HttpRequest<any>\n * @param handler HttpHandler\n */\n intercept(theRequest: HttpRequest<any>, handler: HttpHandler): Observable<HttpEvent<any>> {\n debugger;\n const jwtKey = this.userService.getJwtString();\n const authReq = theRequest.clone({\n headers: new HttpHeaders({\n \'Content-Type\': \'application/json\',\n \'Authorization\': `Bearer ${jwtKey}`\n })\n });\n console.log(\'Intercepted HTTP call\', authReq);\n return handler.handle(authReq);\n }\n\n}\nRun Code Online (Sandbox Code Playgroud)\n角度用户服务
\nimport { Injectable } from \'@angular/core\';\nimport { HttpClient, HttpHeaders, HttpParams } from \'@angular/common/http\';\nimport { Router } from \'@angular/router\';\nimport { AuthenticationConfigurationService } from \'./authentication-configuration.service\';\nimport { User, AuthenticationResponse } from \'./data\';\n\n//Service for users \n\n@Injectable({\n providedIn: \'root\'\n})\nexport class UserService {\n //Attributes\n private jwtString: string = \'\'; //JWT (Jason Web Token)\n private isUserLoggedIn = false; \n\n /**\n * Constructor of UserService. \n * @param router Router\n * @param httpClient HttpClient\n */\n constructor(private router: Router, private httpClient: HttpClient) { }\n\n /**\n * Executes upon user login. \n * @param theUser User \n */\n login(theUser: User) {\n const httpOptions = { headers: new HttpHeaders({ \'Content-Type\': \'application/json\' }) };\n this.httpClient.post(AuthenticationConfigurationService.getAuthenticationURL(\'authenticationURL\') + \'/getjwt\', theUser, httpOptions)\n .subscribe((response: AuthenticationResponse) => {\n this.jwtString = response.jwt;\n this.isUserLoggedIn = true;\n });\n }\n\n /**\n * Executes upon user logout. \n */\n logout() {;\n this.isUserLoggedIn = false; \n this.jwtString = \'\';\n this.navigateToLoginPage();\n }\n\n /**\n * Responsible for returning the JWT (Json Web Token) string.\n * @returns string\n */\n getJwtString(): string {\n return this.jwtString; \n }\n\n /**\n * Responsible for returning whether the user is logged-in. \n * @returns boolean\n */\n userLoggedIn(): boolean {\n return this.isUserLoggedIn;\n }\n\n /**\n * Navigate to the login page. \n */\n private navigateToLoginPage() {\n this.router.navigateByUrl(\'/login\');\n }\n\n}\nRun Code Online (Sandbox Code Playgroud)\n春季启动安全
\npackage com.example.LibraryServer.Security;\n\nimport com.example.LibraryServer.Filter.Security.JwtRequestFilter;\nimport com.example.LibraryServer.Services.LibraryUserDetailsService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.security.authentication.AuthenticationManager;\nimport org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;\nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;\nimport org.springframework.security.config.http.SessionCreationPolicy;\nimport org.springframework.security.crypto.password.NoOpPasswordEncoder;\nimport org.springframework.security.crypto.password.PasswordEncoder;\nimport org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;\nimport org.springframework.web.cors.CorsConfiguration;\nimport org.springframework.web.cors.CorsConfigurationSource;\nimport org.springframework.web.cors.UrlBasedCorsConfigurationSource;\n\nimport java.util.Arrays;\n\n/**\n * Class responsible for security configurations.\n */\n@Configuration\n@EnableWebSecurity\npublic class SecurityConfig extends WebSecurityConfigurerAdapter {\n\n //Attributes\n private final LibraryUserDetailsService libraryUserDetailsService;\n private final JwtRequestFilter jwtRequestFilter;\n\n /**\n * Constructor of SecurityConfig.\n * @param theLibraryUserDetailsService LibraryUserDetailsService\n * @param theJwtRequestFilter JwtRequestFilter\n */\n @Autowired\n public SecurityConfig(LibraryUserDetailsService theLibraryUserDetailsService, JwtRequestFilter theJwtRequestFilter) {\n this.libraryUserDetailsService = theLibraryUserDetailsService;\n this.jwtRequestFilter = theJwtRequestFilter;\n }\n\n /**\n * Responsible for user security configuration.\n * Overridden from WebSecurityConfigurerAdapter level.\n * @param theHttpSecurity HttpSecurity\n * @throws Exception - Exception upon security configuration.\n */\n @Override\n protected void configure(HttpSecurity theHttpSecurity) throws Exception {\n //theHttpSecurity.authorizeRequests()\n //.antMatchers("/**").access("permitAll") //Allow all paths\n /*.and().cors()*/\n //.and().csrf().disable(); //Allow all requests - CSRF (Cross-Site Request Forgery)\n theHttpSecurity.csrf().disable() //Allow all requests - CSRF (Cross-Site Request Forgery)\n .authorizeRequests().antMatchers("/authenticate/**").access("permitAll") //Allow all paths\n .anyRequest().authenticated() //All other paths need authentication\n /*Inform spring security not to manage sessions.\n All requests will be filtered via \'JwtRequestFilter\' with JWT and does not need sessions.*/\n .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);\n\n //Inform spring security about the filter \'JwtRequestFilter\' for username and password authentication.\n theHttpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);\n }\n\n /**\n * Responsible for configuring user-store.\n * Overridden from WebSecurityConfigurerAdapter level.\n * @param theAuthentication AuthenticationManagerBuilder\n * @throws Exception - Exception upon user store creation.\n */\n @Override\n public void configure(AuthenticationManagerBuilder theAuthentication) throws Exception {\n //theAuthentication.inMemoryAuthentication()\n //.withUser("sankalpa")\n //.password("{noop}123")\n //.authorities("ROLE_USER");\n theAuthentication.userDetailsService(libraryUserDetailsService);\n }\n\n /**\n * Method constructing AuthenticationManager bean.\n * This method is needed since AuthenticationManager is being used in \'HelloController\'.\n * Therefore this bean should be in spring application context.\n * Overridden from WebSecurityConfigurerAdapter level.\n * @return AuthenticationManager\n * @throws Exception - Exception upon execution.\n */\n @Override\n @Bean\n public AuthenticationManager authenticationManagerBean() throws Exception {\n return super.authenticationManagerBean();\n }\n\n /**\n * Method constructing a password encoder bean.\n * Constructs \'NoOpPasswordEncoder\'.\n * @return PasswordEncoder\n */\n @Bean\n public PasswordEncoder passwordEncoder() {\n return NoOpPasswordEncoder.getInstance();\n }\n\n}\nRun Code Online (Sandbox Code Playgroud)\nSpring Boot CORS配置类
\npackage com.example.LibraryServer.CORS;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.servlet.config.annotation.CorsRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurer;\n\n/**\n * Configuration class which is responsible for handling CORS.\n * Cross-Origin Resource Sharing (CORS) configuration class.\n */\n@Configuration\npublic class CorsConfiguration implements WebMvcConfigurer {\n\n /**\n * Responsible for CORS mapping.\n * Overridden from WebMvcConfigurer level.\n * @param theRegistry CorsRegistry\n */\n @Override\n public void addCorsMappings(@NotNull CorsRegistry theRegistry) {\n //End points\n var authorizedEndpoints = new String[] {\n "/book/**",\n "/author/**",\n "/authenticate/**"\n };\n\n //Add mapping\n for (var endPoint : authorizedEndpoints) {\n theRegistry.addMapping(endPoint)\n .allowedOrigins("http://localhost:4200")\n .allowedMethods("*") //"HEAD", "GET", "PUT", "POST", "DELETE", "PATCH"\n .allowedHeaders("*")\n .allowCredentials(true)\n .exposedHeaders("Authorization");\n }\n }\n\n}\nRun Code Online (Sandbox Code Playgroud)\n弹簧启动过滤器
\npackage com.example.LibraryServer.Filter.Security;\n\nimport com.example.LibraryServer.Services.LibraryUserDetailsService;\nimport com.example.LibraryServer.Uilities.JsonWebTokenUtility;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.authentication.UsernamePasswordAuthenticationToken;\nimport org.springframework.security.core.context.SecurityContextHolder;\nimport org.springframework.security.core.userdetails.UserDetails;\nimport org.springframework.security.web.authentication.WebAuthenticationDetailsSource;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.filter.OncePerRequestFilter;\n\nimport javax.servlet.FilterChain;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\n\n/**\n * Filter class for intercepting all the requests and validate with JWT (Jason Web Token).\n */\n@Slf4j\n@Component\npublic class JwtRequestFilter extends OncePerRequestFilter {\n\n //Attributes\n private final LibraryUserDetailsService libraryUserDetailsService;\n private final JsonWebTokenUtility jsonWebTokenUtility;\n\n /**\n * Constructor of JwtRequestFilter.\n * @param theLibraryUserDetailsService LibraryUserDetailsService\n * @param theJsonWebTokenUtility JsonWebTokenUtility\n */\n @Autowired\n public JwtRequestFilter(LibraryUserDetailsService theLibraryUserDetailsService, JsonWebTokenUtility theJsonWebTokenUtility) {\n this.libraryUserDetailsService = theLibraryUserDetailsService;\n this.jsonWebTokenUtility = theJsonWebTokenUtility;\n }\n\n /**\n * Responsible for intercepting the request via filter and do the validations and needful with JWT.\n * Overridden from OncePerRequestFilter level.\n * @param theRequest HttpServletRequest\n * @param theResponse HttpServletResponse\n * @param theChain FilterChain\n * @throws ServletException - Exception upon execution.\n * @throws IOException - Exception upon execution.\n */\n @Override\n protected void doFilterInternal(HttpServletRequest theRequest, HttpServletResponse theResponse, FilterChain theChain)\n throws ServletException, IOException {\n printLog("doFilterInternal() -> Executed");\n //Get the \'Authorization\' from the request header. JWT is suppose to send in request header under \'Authorization\'.\n final String authorizationHeader = theRequest.getHeader("Authorization");\n\n //Method local attributes\n String username = null;\n String jwt = null;\n\n //Get the JWT String and username out from \'authorizationHeader\'\n if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {\n printLog("doFilterInternal() -> Extracting the JWT token from the authorization header");\n jwt = authorizationHeader.substring(7);\n username = jsonWebTokenUtility.extractUserName(jwt);\n }\n\n if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {\n printLog("doFilterInternal() -> User name found: " + username + " and there is no current logged-in user");\n //If the username is not null and there is no current user authenticated\n\n //Get the user from user details service\n UserDetails userDetails = this.libraryUserDetailsService.loadUserByUsername(username);\n\n if (jsonWebTokenUtility.validateToken(jwt, userDetails)) {\n printLog("doFilterInternal() -> Load user for the username: " + userDetails.getUsername() +\n " and validated the JWT successfully");\n //Validating user with the JWT String is successful\n\n //Create token\n UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =\n new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());\n printLog("doFilterInternal() -> Created \'UsernamePasswordAuthenticationToken\'");\n //Set the information to the token\n usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(theRequest));\n printLog("doFilterInternal() -> Set details to the \'UsernamePasswordAuthenticationToken\'");\n //Set the authorized user to the context\n SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);\n printLog("doFilterInternal() -> Set \'UsernamePasswordAuthenticationToken\' to the \'SecurityContextHolder\'");\n }\n }\n //Continue the chain\n printLog("doFilterInternal() -> Continue the chain...");\n theChain.doFilter(theRequest, theResponse);\n }\n\n /**\n * Responsible for printing main log messages to the console.\n * @param theLogMessage String\n */\n private void printLog(String theLogMessage) {\n log.info("JwtRequestFilter: " + theLogMessage);\n }\n\n}\nRun Code Online (Sandbox Code Playgroud)\n在上面的过滤器中,我想从标头中获取“授权”,但请求根本没有标头。当我通过邮递员做同样的事情时,效果非常好。当我通过 Angular 客户端执行此操作时会发生这种情况。
\n\n小智 8
有同样的问题。就我而言,我在飞行前调用中遇到了 cors 错误。添加 http.cors() 如下解决了我的问题。
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().cacheControl();
http.csrf().disable()
.authorizeRequests()
.....;
http.cors();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6167 次 |
| 最近记录: |