我在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)));
}
答案 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)));
}
}