【发布时间】:2017-09-13 05:16:07
【问题描述】:
我正在使用 Angular 2 并尝试在 get 方法上发送标头参数。我有以下代码:
let tokenUrl2 = "http://localhost:8080/users";
let headers = new Headers();
headers.append('abc', token);
let options = new RequestOptions({ headers: headers });
return this.http.get(tokenUrl2, options);
我收到此错误:
Response for preflight is invalid (redirect)
我也添加了这些参数,但我得到了同样的错误:
headers.append('Content-Type', 'application/json');
headers.append('Authorization':'Bearer ' + token);
谁能告诉我发送标头参数的正确方法是什么。非常感谢:)
编辑 1
网址“http://localhost:8080/users”来自 Spring Boot Web 应用程序(它是一个 REST 服务)。我正在尝试将 Angular 应用程序与 Spring Boot 应用程序进行通信。我的想法是向它发送一个先前从另一个 REST 服务获得的令牌。在第一个 REST 服务中,我得到了一个令牌。这是一个带有 POST 的 REST 服务,它可以工作。然后,我通过 GET 方法将此令牌发送到第二个 REST 服务 (http://localhost:8080/users)。这第二部分不起作用。我尝试将 GET 方法更改为 POST,因为在第一部分使用 POST 方法确实可以工作,但是这个新的更改都不起作用。我仍然收到相同的消息:预检响应无效(重定向)。
我有这些问题:
如果我的第一个 REST 服务(使用 POST 实现)可以工作,为什么第二个不工作?这是因为我的请求(我的 Angular 应用程序)没有实现 CORS?
我希望有了这些细节,你可以帮助我解决我的问题。
谢谢!
编辑 2
最初,我认为我只是在从 Angular 应用程序向 REST 服务发送标头参数时出错。但是,我进行了调查,发现我的问题涉及更多组件。我讲述我的组件:
我有一个 Angular 应用程序需要使用 Spring Boot 应用程序中的 REST 服务。每个 REST 服务都需要身份验证,为此我使用 JWT。
首先。我的 Angular 应用程序使用经过身份验证的 REST 服务。如果这样做了。 REST 服务返回一个令牌。
第二。有了这个令牌,Angular 应用程序可以使用另一个受 Spring Security 保护的 REST 服务。
我的错误发生在第二步。我不能消费其他服务。我有一个从 OncePerRequestFilter 扩展的自定义过滤器,甚至没有被调用。在 Angular 应用程序中,我收到一条我之前报告过的消息:
预检响应无效(重定向)
正如我在之前的编辑中所说的那样。我不理解,因为第一个 REST 服务被调用但第二个没有。我也不明白为什么我的自定义过滤器没有被调用。我认为我从 Angular 应用程序中调用错误。
我的代码:
自定义过滤器:
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
private final Log logger = LogFactory.getLog(this.getClass());
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Value("${jwt.header}")
private String tokenHeader;
static final String ORIGIN = "Origin";
@Override
//@CrossOrigin(origins = "*")
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// TODO Auto-generated method stub
logger.info("checking authentication für user ");
String authToken = request.getHeader(this.tokenHeader);
// authToken.startsWith("Bearer ")
// String authToken = header.substring(7);
String username = jwtTokenUtil.getUsernameFromToken(authToken);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
// It is not compelling necessary to load the use details from the database. You could also store the information
// in the token and read it from it. It's up to you ;)
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
// For simple validation it is completely sufficient to just check the token integrity. You don't have to call
// the database compellingly. Again it's up to you ;)
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
logger.info("authenticated user " + username + ", setting security context");
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
filterChain.doFilter(request, response);
}
}
Angular 控制器和服务:
import { Component, OnInit } from '@angular/core';
import { LoginService } from './login.service';
interface TokenJson {
token: string;
}
@Component({
selector: 'login',
templateUrl: 'login.component.html',
styleUrls: ['login.scss'],
providers: [LoginService]
})
export class LoginComponent implements OnInit {
private model = {'username':'****', 'password':'****'};
private currentToken:string ;
private tokenJson: TokenJson;
// constructor
constructor(private _loginService: LoginService) {
}
// on-init
ngOnInit() {
debugger;
this._loginService.sendCredential(this.model).subscribe(
data => {
debugger;
//localStorage.setItem("token", JSON.parse(JSON.stringify(data)).token);
// this.currentToken = JSON.parse(JSON.stringify(data))._body;
this.tokenJson = JSON.parse(JSON.stringify(data))._body;
this.currentToken = JSON.parse(JSON.parse(JSON.stringify(data))._body).token;
localStorage.setItem("token", this.currentToken);
this._loginService.sendToken(localStorage.getItem("token")).subscribe(
data => {
//this.currentUserName=this.model.username;
//localStorage.setItem("currentUserName", this.model.username);
debugger;
this.model.username='';
this.model.password='';
},
error => {
debugger;
console.log(error)
}
);
},
error => {
debugger;
console.log(error)
}
);
}
}
import {Injectable} from "@angular/core";
import {Http, Headers, Response, RequestOptions} from '@angular/http';
import {Observable} from 'rxjs/Observable';
@Injectable()
export class LoginService {
token: string;
constructor (private http: Http) {}
sendCredential(model) {
debugger;
let tokenUrl1 = "http://localhost:8080/auth";
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.post(tokenUrl1, JSON.stringify(model), {headers: headers});
}
sendToken(token) {
debugger;
let tokenUrl2 = "http://localhost:8080/users";
console.log('Bearer '+token);
let getHeaders2 = new Headers();
getHeaders2.append('Authorization', token);
let headers = new Headers();
headers.append('authorization', token);
return this.http.post(tokenUrl2, {}, options);
}
}
解决方案
我发现了问题。针对 OPTIONS 类型的请求收到的错误消息。我只是避免了这种类型的请求。我在安全配置类中添加了以下配置:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
}
//
}
PD:我从here指导
【问题讨论】:
标签: angular spring-boot get cors