2017-04-17 122 views
0

我正在使用Angular 2並試圖在get方法上發送頭部參數。我有下面的代碼:Spring Boot + Angular 2 + JWT

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

的URL 「http://localhost:8080/users」 是從春天啓動的Web應用程序(這是一個REST服務)。我試圖與春季啓動應用程序溝通角應用程序。我的想法是將其從另一個REST服務獲得的標記發送給它。在第一個REST服務中,我得到了一個令牌。這是POST的REST服務,它可以工作。然後,我通過GET方法將此令牌發送給第二個REST服務(http://localhost:8080/users)。第二部分不起作用。我嘗試將GET方法更改爲POST,因爲使用POST方法的第一部分可以正常工作,但這種新更改不起作用。我仍然收到相同的消息:預檢的響應無效(重定向)

我有以下問題:

如果我的第一個REST服務(含郵政設立)的作品,爲什麼第二個不?這是因爲我的請求(我的角應用程序)沒有實現CORS?

我希望有這個細節,你可以幫我解決我的問題。

謝謝!

EDIT 2

起初,我以爲從角應用發送頭參數REST服務時,我只有一個錯誤。但是,我調查了一下,發現我的問題涉及更多組件。我告訴我的組件:

我有一個角度的應用程序,需要從Spring啓動應用程序使用REST服務。每個REST服務都需要身份驗證,因此我使用JWT。

首先。我的角度應用程序使用認證REST服務。如果這樣做。 REST服務返回一個令牌。

二。有了這個令牌,角度應用程序可以使用Spring Security保護的另一個REST服務。

我的錯誤發生在第二步。我無法使用其他服務。我有一個自定義過濾器,從OncePerRequestFilter延伸,甚至沒有被調用。在角應用,我感到我之前報道的消息:

預檢

響應無效(重定向)

正如我在以前的編輯說。我不理解,因爲第一個REST服務被調用,但第二個沒有。我也不明白爲什麼我的自定義過濾器沒有被調用。我認爲我從角度應用程序調用錯誤。

我的代碼:

自定義過濾器:

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); 
    } 
} 

角控制器和服務:

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); 
    } 



} 

SOLUTION

我發現這個問題。該錯誤消息得到了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

回答

1
Response for preflight is invalid (redirect) 

這聽起來更像是您的服務器不正確地處理飛行前請求指導。

您使用的是CORS嗎? (即,您使用ng serve來運行您的Angular應用程序,但嘗試訪問不同端口/機器上的服務器?)。

因爲,根據您所得到的錯誤,我認爲您的後端服務器沒有設置爲正確處理CORS。

+0

我用命令「npm start」運行我的應用程序。你認爲這是問題嗎? –

+0

更可能,您正面臨CORS問題。基本上,您正在從一臺服務器提供瀏覽器應用程序,但試圖從該應用程序向另一臺服務器發出http請求。瀏覽器不允許出於安全原因,除非其他服務器通過在其響應中設置適當的標頭明確允許它。 Google的「CORS」可以稍微閱讀一下。我假設你有控制其他服務器來配置CORS。如果你沒有這種控制,那麼你將不得不調查在你的「npm start」服務器上設置一個代理 – snorkpete

+0

我忘記告訴我的角度應用程序消耗一個春季啓動應用程序。 URL是我的春季啓動應用程序的get方法。我改爲開機自檢,但它不起作用。我在第一篇文章中解釋mot詳細 –

0
let requestOptions = new RequestOptions({ 
     headers: new Headers({ 
      'Content-Type': 'application/json' 
     }), 
     method: RequestMethod.Post, 
     body: {} 
    }); 

    this.http.request("http://localhost:8080/users", requestOptions) 
     .map((response: Response) => response.json()) 
+0

爲什麼參數「方法」是:RequestMethod.Post?爲什麼是POST?它不應該是GET? –

+0

只需將其更改爲'RequestMethod.Get' –

+0

我收到此錯誤消息:無法找到名稱'RequestMethod' –