Rest API返回401时出现CORS错误

时间:2017-04-11 20:41:15

标签: rest angular rest-client

我在Spring中使用REST API作为后端,将Angular 2作为前端。

我称之为登录网址。当响应是201时它很好,但是当我发送401/403时,我有一个错误。

XMLHttpRequest cannot load http://localhost:8888/emot/login. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 401.

在所有请求中出现此错误之前,我更改了客户端中的调用方法:

 authenticate(login: string, password: string) {

    let headers = this.createBasicHeaders();
    this.createAuthorizationHeader(headers, login, password);
    const options = new RequestOptions({headers: headers});

    console.log(this.http.post(this.restApi + "/emot/login", '{}', options)
      .map(this.extractData)
      .toPromise()
      .catch(this.handleError));

  }


  createAuthorizationHeader(headers: Headers, login: string, password: string) {
    headers.append('Authorization', 'Basic ' +
      btoa(login + ':' + password));
  }

  createBasicHeaders(): Headers {
    let headers = new Headers();

    headers.append('Content-Type', 'application/json');
    // Website you wish to allow to connect
    headers.append('Access-Control-Allow-Origin', this.restApi);

    // Request methods you wish to allow
    headers.append('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

    // Request headers you wish to allow
    headers.append('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

    // Set to true if you need the website to include cookies in the requests sent
    // to the API (e.g. in case you use sessions)
    headers.append('Access-Control-Allow-Credentials', 'true');

    return headers;
  }

  private extractData(res: Response) {
    const body = res.json();
    console.log("GOOD");
    return body.data || {};
  }

  private handleError(error: Response | any) {
    let errMsg: string;
    if (error instanceof Response) {
      const body = error.json() || '';
      const err = body.error || JSON.stringify(body);
      errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
    }
    else {
      errMsg = error.message ? error.message : error.toString();
    }
    return Observable.throw(errMsg);
  }

我的服务器控制器:

@RestController
@ComponentScan("xxxx")
@RequestMapping("/xxx")
@CrossOrigin(origins = "*")
public class RootRequestDispatcher {

    @Autowired
    OperatorFacade operatorFacade;

    @RequestMapping(value = "login", method = RequestMethod.POST)
    public ResponseEntity<OperatorDTO> logon(Authentication auth) {

        System.out.println(auth);
        OperatorDTO operator = operatorFacade.findOperatorByLogin(auth.getName());

        return new ResponseEntity<OperatorDTO>(operator, HttpStatus.OK);
    }
}

当操作员信号不正确时发出响应:

@Override
public void commence(HttpServletRequest request,
                     HttpServletResponse response,
                     AuthenticationException authException) throws IOException, ServletException {
    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    response.addHeader(SecurityProperties.HEADER_NAME_REALM, SecurityProperties.HEADER_VALUE_REALM + getRealmName());
    authException.printStackTrace();
    System.out.println("TESTING ERROR");
    ObjectMapper mapper = new ObjectMapper();
    PrintWriter writer = response.getWriter();
    writer.println(mapper.writeValueAsString(new ExceptionBean(Causes.ANOTHER_CAUSE)));
}

1 个答案:

答案 0 :(得分:0)

我发现自己解决了。

对于这个问题,需要覆盖AccessDeniedHandler bean。而不是像我之前发表的那样。

public class CustomAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest,
                       HttpServletResponse httpServletResponse,
                       AccessDeniedException e) throws IOException, 
    ServletException {
        httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
        httpServletResponse.addHeader(SecurityPathProperties.HEADER_NAME_REALM,
                SecurityPathProperties.HEADER_VALUE_REALM + SecurityPathProperties.REALM);
        ObjectMapper mapper = new ObjectMapper();
        PrintWriter writer = httpServletResponse.getWriter();
        writer.println(mapper.writeValueAsString(new ExceptionBean(ExceptionCauses.NOT_FOUND_USER)));
    }
}