如何处理 spring security + angular 中的 401 错误?

Posted

技术标签:

【中文标题】如何处理 spring security + angular 中的 401 错误?【英文标题】:How to handle a 401 error in spring security + angular? 【发布时间】:2020-11-17 15:17:45 【问题描述】:

我正在关注如何使用 spring security 和 angular 进行登录身份验证的教程,但是每当我运行 angular 程序并尝试登录时,我都会收到 401 错误。我觉得这是一个 cors 问题并创建了一个 cors 过滤器类,这是一个类似问题的解决方案,但我仍然遇到同样的错误。登录详细信息是正确的,因为我使用相同的凭据登录到后端的 localhost:8080 但是当我尝试使用前端登录时,我在索引中收到以下错误。

错误:

请求网址:http://localhost:8080/login

请求方法:GET

状态码:401

远程地址:[::1]:8080

推荐人政策:no-referrer-when-downgrade

Access-Control-Allow-Headers:access_token、授权、内容类型

访问控制允许方法:POST、PUT、GET、OPTIONS、DELETE

访问控制允许来源:*

访问控制最大年龄:4200

Cache-Control: no-cache, no-store, max-age=0, must-revalidate

连接:保持活动

内容长度:0

日期:格林威治标准时间 2020 年 7 月 28 日星期二 07:47:34

过期:0

保持活动状态:超时=60

编译指示:无缓存

变化:原产地

变化:访问控制请求方法

变化:访问控制请求标头

WWW-Authenticate: Basic realm="Realm"

WWW-Authenticate: Basic realm="Realm"

X-Content-Type-Options: nosniff

X 帧选项:拒绝

X-XSS-保护:1;模式=块

接受:application/json、text/plain、/

接受编码:gzip、deflate、br

接受语言:en-GB,en-US;q=0.9,en;q=0.8

授权:Basiccml6YW5hOmp0MTQz

连接:保持活动

主机:本地主机:8080

来源:http://localhost:4200

引用:http://localhost:4200/login

Sec-Fetch-Dest:空

Sec-Fetch-Mode:cors

Sec-Fetch-Site:同一站点

用户代理:Mozilla/5.0(Linux;android 6.0;Nexus 5 Build/MRA58N)

AppleWebKit/537.36 (Khtml, like Gecko) Chrome/84.0.4147.89 Mobile Safari/537.36

我试过了:

Angular 2 Spring Boot Login CORS Problems

教程:

https://www.youtube.com/watch?v=QV7ke4a7Lvc

弹簧安全配置

@Configuration
public class SpringConfig extends WebSecurityConfigurerAdapter 


    @Autowired
    private CORSFilter myCorsFilter;


//CORS


    @Override
    protected void configure(HttpSecurity http) throws Exception 
     /*   http.cors().and().csrf().
                disable()
                .authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS, "/**")
                .permitAll()
                .anyRequest()
                .fullyAuthenticated()
                .and()
                .httpBasic();*/

        http.addFilterBefore(myCorsFilter, ChannelProcessingFilter .class);


        http.cors();
        http.csrf().disable();
        http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and()
                .httpBasic();
    



    protected void configure(AuthenticationManagerBuilder auth) throws Exception
        auth.inMemoryAuthentication()
                .withUser("java")
                .password("noopjt143").roles("USER");


    



Corsfilter 类


@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CORSFilter implements Filter 

    /**
     * CORS filter for http-request and response
     */
    public CORSFilter() 
    

    /**
     * Do Filter on every http-request.
     */

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException 
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "4200");
        response.setHeader("Access-Control-Allow-Headers", "access_token, authorization, content-type");

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) 
            response.setStatus(HttpServletResponse.SC_OK);
         else 
            chain.doFilter(req, res);
        
    

    /**
     * Destroy method
     */
    @Override
    public void destroy() 
    

    /**
     * Initialize CORS filter
     */
    @Override
    public void init(FilterConfig arg0) throws ServletException 
    


@RestController
@CrossOrigin(origins = "*")
public class CashierController 



        @Autowired
        private CashierRepo repository;

        @GetMapping("/login")
        public String login()
            return "authenticated";
        


        @PostMapping("/addUser")
        public String saveCashier(@RequestBody Cashier cashier) 
            repository.save(cashier);
            return "Added user with user id : " + cashier.getUserId();

        

【问题讨论】:

【参考方案1】:

似乎您没有从 Spring 安全性中排除您的登录 API。每当我们启用 Spring Security 时,我们必须配置不应对其施加安全性的 URL 列表。示例 - 登录 api、html 文件、js 文件等。您可以通过将以下方法添加到 SpringConfig 类来做到这一点

@Override
    public void configure(WebSecurity web) throws Exception 
    
        // Allow Login API to be accessed without authentication
        web.ignoring().antMatchers("/login").antMatchers(HttpMethod.OPTIONS, "/**"); // Request type options should be allowed.
    

【讨论】:

欢迎。只是补充。如果您想排除任何其他 URL 或资产,您可以用相同的方法用逗号分隔它们。示例 - .antMatchers("/login","/**.js","/register") 另外,除了cb.greatest,你也可以使用cb.max

以上是关于如何处理 spring security + angular 中的 401 错误?的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security登录成功后如何处理用户信息

如何处理 spring security + angular 中的 401 错误?

如何处理 grails spring-security-rest 插件中的自定义身份验证异常?

Spring Boot 如何处理可抛出对象

如何处理具有相同实体 ID 的两个 IDP

如何处理 Spring 集成流的事务(Java DSL)