Angular2/4/5基于令牌认证安全调用WebAPI接口的实现
Hey there! Let's get your token-based authentication working properly for your Web API calls. Here's how to integrate the token into your service calls and make the implementation cleaner and more secure:
Step 1: Refactor UserService to Add Token to Request Headers
First, let's create a reusable method to build authentication headers, then update your API methods to use this header. This avoids repeating code across all authenticated endpoints.
Here's the updated user.service.ts:
import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { UIHelperClass } from '../UIHelperClasses/UIHelperClass'; import { Person } from './person.model'; @Injectable() export class UserService { constructor(private http: HttpClient, private uihelper: UIHelperClass) {} // Private method to get authenticated headers private getAuthHeaders(): HttpHeaders { const userToken = localStorage.getItem('userToken'); let headers = new HttpHeaders(); // Add Bearer token if available if (userToken) { headers = headers.set('Authorization', `Bearer ${userToken}`); } return headers; } UserForm(person: Person){ const body: Person = { FirstName: person.FirstName, LastName: person.LastName }; // Use our authenticated headers for this secured endpoint return this.http.post( this.uihelper.CallWebAPIUrl("/api/User/AddUser"), body, { headers: this.getAuthHeaders() } ); } userAuthentication(userName, password) { var data = "username=" + userName + "&password=" + password + "&grant_type=password"; var reqHeader = new HttpHeaders({ 'Content-Type': 'application/x-www-urlencoded', 'No-Auth':'True' // Keep this since login doesn't require prior auth }); return this.http.post(this.uihelper.CallWebAPIUrl("/token"), data, { headers: reqHeader }); } getUserClaims(){ // Add auth headers to this secured request too return this.http.get( this.uihelper.CallWebAPIUrl("/api/GetUserClaims"), { headers: this.getAuthHeaders() } ); } }
Key Changes Explained:
- Reusable
getAuthHeaders()Method: This method checks for a stored token and builds theAuthorizationheader with the standardBearerscheme. Every authenticated request uses this consistent logic, so you don't have to duplicate code. - Updated
UserFormandgetUserClaims: These methods now use authenticated headers instead of theNo-Authheader, since those endpoints require a valid token to access. - Preserved
userAuthentication: The login endpoint keeps theNo-Authheader as intended—you don't have a token yet when logging in, so this request should bypass auth checks.
Step 2: Clean Up Home Component's OnSubmit Method
In your home.ts, the line localStorage.getItem('userToken'); doesn't actually do anything right now. Since we're handling token injection in the service, you can remove it. Here's the cleaned-up method:
OnSubmit(form: NgForm) { this.userService.UserForm(form.value) .subscribe((data: any) => { if (data.Succeeded == true) { console.log("Form submitted successfully!"); // Add your success logic here (e.g., reset the form, show a toast notification) } }, (err) => { // Don't forget to handle errors like expired tokens or invalid requests console.error("Error submitting form:", err); }); }
Bonus: Use Angular HttpInterceptor for Global Token Injection
For a more scalable solution, consider using an HttpInterceptor to automatically add the token to every outgoing request. This means you don't have to call getAuthHeaders() in every service method.
Here's a quick implementation example:
import { Injectable } from '@angular/core'; import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable() export class AuthInterceptor implements HttpInterceptor { intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { // Skip adding token for requests marked as No-Auth (like login) if (request.headers.get('No-Auth') === 'True') { return next.handle(request); } const userToken = localStorage.getItem('userToken'); if (userToken) { // Clone the request and inject the Authorization header const clonedRequest = request.clone({ headers: request.headers.set('Authorization', `Bearer ${userToken}`) }); return next.handle(clonedRequest); } return next.handle(request); } }
Then register the interceptor in your app.module.ts:
import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { AuthInterceptor } from './auth.interceptor'; @NgModule({ ... providers: [ { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true } ], ... }) export class AppModule { }
With this interceptor, all requests automatically get the token added unless you explicitly mark them with No-Auth: True.
Quick Security Notes
- Token Storage:
localStorageis common for SPAs, but it's vulnerable to XSS attacks. If your app handles sensitive data, consider using HttpOnly cookies (this requires backend changes to support cookie-based auth). - Token Expiry: Add logic to handle expired tokens (e.g., redirect to login when you get a 401 Unauthorized response).
- HTTPS: Always use HTTPS in production to prevent token interception.
内容的提问来源于stack exchange,提问作者Shailesh Bhat

