Java Spring Security ionic4 HTTP 请求

标签 java spring typescript spring-security ionic3

我有一个 Java Springboot REST api,我也尝试从 ionic4 Web 应用程序发送 POST 请求。不幸的是我无法让登录后工作。当它仅发送预检选项请求时,我会收到 HTTP 状态 401403200

我在 StackOverflow 上检查过类似的帖子,例如 this但他们刚刚改变了我收到的错误。下面是我从各种教程和其他 SO 帖子中获取一些信息后得到的结果。

不确定我的错误是否与 Spring SecurityConfiguration 或 TypeScript post 请求有关。

我的 Spring 安全配置

@EnableWebSecurity
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
@EnableGlobalMethodSecurity(securedEnabled = true)
class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {

        http
            .authorizeRequests()

            .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
            .antMatchers("/login").permitAll()
            .antMatchers(HttpMethod.OPTIONS).permitAll()
            .anyRequest().authenticated()
            .and()
            .addFilterBefore(new RestConfig().corsFilter(), CsrfFilter.class)
            .csrf().csrfTokenRepository(csrfTokenRepository()).and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
            .formLogin().loginProcessingUrl("/login")
            .successHandler(successHandler())
            .failureHandler(failureHandler())
            .and()
            .exceptionHandling()
            .and()
            .csrf().disable();
    }

    private AuthenticationSuccessHandler successHandler() {
        return new AuthenticationSuccessHandler() {

            @Override
            public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                httpServletResponse.getWriter().append("OK");
                httpServletResponse.setStatus(200);
            }
        };
    }

    private AuthenticationFailureHandler failureHandler() {
        return new AuthenticationFailureHandler() {

            @Override
            public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                httpServletResponse.getWriter().append("Authentication failure");
                httpServletResponse.setStatus(401);
            }
        };
    }

    private AccessDeniedHandler accessDeniedHandler() {
        return new AccessDeniedHandler() {

            @Override
            public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
                httpServletResponse.getWriter().append("Access denied");
                httpServletResponse.setStatus(403);
            }
        };
    }

    private AuthenticationEntryPoint authenticationEntryPoint() {
        return new AuthenticationEntryPoint() {

            @Override
            public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                httpServletResponse.getWriter().append("Not authenticated");
                httpServletResponse.setStatus(401);
            }
        };
    }

    private Filter csrfHeaderFilter() {
        return new OncePerRequestFilter() {

            @Override
            protected void doFilterInternal(HttpServletRequest request,
                                        HttpServletResponse response, FilterChain filterChain)
                throws ServletException, IOException {
                     CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
                     if (csrf != null) {
                         Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
                        String token = csrf.getToken();
                        if (cookie == null || token != null
                        && !token.equals(cookie.getValue())) {
                            cookie = new Cookie("XSRF-TOKEN", token);
                            cookie.setPath("/");
                            response.addCookie(cookie);
                        }
                    }
                response.setHeader("Access-Control-Allow-Origin", "*");
                response.setHeader("Access-Control-Allow-Headers", "*");
                response.setHeader("Access-Control-Allow-Credentials", "*");
                response.setHeader("Access-Control-Allow-Methods", "*");
                response.setHeader("Access-Control-Max-Age", "3600");
                filterChain.doFilter(request, response);
            }
        };
    }

    private CsrfTokenRepository csrfTokenRepository() {
        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
        repository.setHeaderName("X-XSRF-TOKEN");
        repository.setSessionAttributeName("_csrf");
        return repository;
   }

我的 TypeScript POST

onLogin(loginData: {username: string, password: string}) {
    let headers = new Headers();
    headers.append('Access-Control-Allow-Credentials', 'true');
    headers.append('Content-Type','application/x-www-form-urlencoded');
    headers.append("Authorization", "Basic " + btoa(loginData.username + ":" + loginData.password));


    let body = {
        username: loginData.username,
        password: loginData.password
    }
    this.http.post('http://localhost:5000/login', body, {headers: headers, withCredentials: true})
      .map(res => res.json())
      .subscribe(data => {
          console.log(data);
          console.log(data.status)
       });
  }
}

上面的代码出现错误,我知道这不是登录详细信息,因为相同的用户名和密码可以通过 swagger 完美地工作,只是不在 POST 中。

ionic error

最佳答案

这就是我解决问题的方法。

onLogin(loginData: {username: string, password: string}) {
  let headers = new Headers();
  headers.append('Access-Control-Allow-Credentials', 'true');
  headers.append('Content-Type','application/x-www-form-urlencoded');

  let body = `username=${loginData.username}&password=${loginData.password}`;

  this.http.post('http://localhost:5000/login', body, {headers: headers})

    .map(res => res)
    .subscribe(data => {
      console.log(data.status);
      if (data.status == 200) {
        this.navCtrl.push(TabsPage);
      }
      else {
        this.showError("Invalid username or password");
      }

    });
}

更新: 主要问题是 URL-encoding这一行:

let body = `username=${loginData.username}&password=${loginData.password}`;

感谢dur

关于Java Spring Security ionic4 HTTP 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44556251/

相关文章:

java - Apache Tika 将 AC3 文件解析为 application/octet-stream 而不是 audio/ac3

Java FX 与 Firebase Storage 连接用于上传图片

javascript - Angular2 形式的嵌套组?

在定义返回接口(interface)的函数时,Typescript 的行为似乎不一致

java - 如何确保第三方API正常工作

java - 将 Map 的键值对作为对象访问

java - 从 Spring 属性传递 Apache Camel 端点 Uri

java - 依赖jar中的异步注释,不启动新线程

java - Hibernate的ManyToMany简单使用

typescript - 如何从命令行检查 TypeScript 代码的语法错误?