将 x-auth-token 发送到 Spring Boot 时,Angular 应用程序出现 401 错误,我做错了啥?

Posted

技术标签:

【中文标题】将 x-auth-token 发送到 Spring Boot 时,Angular 应用程序出现 401 错误,我做错了啥?【英文标题】:Angular app getting 401 error when sending x-auth-token to spring boot ,what am i doing wrong?将 x-auth-token 发送到 Spring Boot 时,Angular 应用程序出现 401 错误,我做错了什么? 【发布时间】:2021-01-25 12:13:33 【问题描述】:

我有一个带有 Spring Boot 后端项目的 Angular 2 前端。初始登录页面接受用户名和密码并将其发送到后端并得到"xAuthToken"作为响应,我存储在localstorage中,当我尝试刷新页面时,角度得到401错误。我怎样才能让spring security接受@ 987654323@?

角度 -

@Injectable()
export class LoginService 

  constructor(private http:Http)  

  sendCredentials(username:String,password:String)
      let url="http://localhost:8181/token";
      let encodedCred=btoa(username+":"+password);
      let basicHeader="Basic "+encodedCred;
      let header=new Headers(
        "Content-Type":  "application/json",
        "Authorization": basicHeader
      );
   return this.http.get(url,headers:header);
  

  checkSession()
    let url="http://localhost:8181/checkSession";
    console.log("pp=="+localStorage.getItem('xAuthToken'));
    let header=new Headers(
      'x-auth-token':  localStorage.getItem('xAuthToken')
    );
 return this.http.get(url,headers:header);
  






export class LoginComponent implements OnInit 

 private credentials="username":"","password":"";
 private loggedIn:boolean=false;

  constructor(private loginService:LoginService)  

  onSubmit()
    this.loginService.sendCredentials(this.credentials.username,this.credentials.password).
    subscribe(res => 
            console.log(res);
            console.log(res.json());
            localStorage.setItem("xAuthToken", res.json().token);
            this.loggedIn=true;
            //location.reload();
          ,
          error => 
            console.log(error);
          
      );
  
  
  
  
  ngOnInit() 
    this.loginService.checkSession().subscribe(
      res=>
        this.loggedIn=true;
      ,
      error=>
        console.log(error);
      
    );
  


春天-

@CrossOrigin(origins = "http://localhost:4200")
@RestController
public class LoginController 

    @Autowired
    private UserService userService;
    
    @RequestMapping(value = "/token")
    public Map<String, String> token(HttpSession session, HttpServletRequest request) 
        System.out.println(request.getRemoteHost());
        
        String remoteHost = request.getRemoteHost();
        int portNumber = request.getRemotePort();
        
        System.out.println(remoteHost+":"+portNumber);
        System.out.println(request.getRemoteAddr());
        
        return Collections.singletonMap("token", session.getId());
    
    @CrossOrigin(origins = "http://localhost:4200",allowedHeaders = "x-auth-token")
    @RequestMapping(value = "/checkSession")
    public ResponseEntity checkSession() 
        System.out.print("insiden checksession");
        return new ResponseEntity("Session Active", HttpStatus.OK);
     
    





@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
    
    @Autowired
    Environment env; 

    @Autowired
    UserSecurityService useSecurityService;
    
    private BCryptPasswordEncoder passwordEncoder() 
        return SecurityUtility.passwordEncoder();
    
    
    private static final String[] PUBLIC_MATHCES= 
            "/css/**",
            "/js/**",
            "/image/**",
            "/book/**",
            "/user/**"
    ;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.userDetailsService(useSecurityService).passwordEncoder(passwordEncoder());
        
        
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http.authorizeRequests()
            .antMatchers(PUBLIC_MATHCES).permitAll()
            .anyRequest().authenticated();
        http.csrf().disable()
            .cors()
            .and()
            .httpBasic();
        
    
    
    
    
    

【问题讨论】:

【参考方案1】:

身份验证流程似乎没有完全通过。您需要通过拦截 HTTP 请求并注入用户来编写对用户的身份验证,然后只有 spring 提供对经过身份验证的路径的访问。

@Autowired
private MyBasicAuthenticationEntryPoint authenticationEntryPoint;

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception 
    auth.inMemoryAuthentication()
      .withUser("user1").password(passwordEncoder().encode("user1Pass"))
      .authorities("ROLE_USER");


@Override
protected void configure(HttpSecurity http) throws Exception 
    // ... standard code here ...

    http.addFilterAfter(new CustomFilter(),
      BasicAuthenticationFilter.class);


@Bean
public PasswordEncoder passwordEncoder() 
    return new BCryptPasswordEncoder();

请参考Baeldung post for spring security auth

【讨论】:

你的答案太复杂了,我不明白,有没有办法使用注释来做到这一点?你能把你的答案分解成简单的术语吗?@Amal George Thomas 您必须在 HTTP 请求中添加一个拦截器,即 SecurityConfig#configure 方法中的 http.addFilterBefore()。在里面你可以有从授权中提取会话令牌的逻辑,并通过设置 SecurityContextHolder.getContext().setAuthentication(authenticationToken); 来验证用户。我刚刚找到了一种可行的简单方法,我会更新我的答案。

以上是关于将 x-auth-token 发送到 Spring Boot 时,Angular 应用程序出现 401 错误,我做错了啥?的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS:未发送 X-Auth-Token(错误 401)

JSESSIONID 或 X-AUTH-TOKEN 在 Spring boot 中对同一用户进行身份验证时重复

如何使用 asp.net core api 在其标头中授权带有 x-auth-token 的请求?

Spring 安全 REST API

Edusoho之X-Auth-Token

Authentication与X-AUTH-Token