Angular与C#登录集成后重定向异常问题求助
问题描述
我正在做一个POC,用C#保护我的Angular应用。我在C#中创建了一个登录页面(运行在https://localhost:7139/account/login),现在想要保护运行在https://localhost:4200的Angular应用,防止未授权用户访问。目前我硬编码了登录凭据,并尝试通过在Angular中创建resolver来实现保护。
现有代码
C# 登录页面(login.cshtml)
<div class="container border" style="padding:20px"> <form method="post"> <div class="text-danger" asp-validation-summary="ModelOnly"></div> <div class="form-group row"> <div class="col-3"> <label asp-for="Credential.Username"></label> </div> <div class="col-5"> <input type="text" asp-for="Credential.Username" class="form-control" /> </div> <div class="text-danger" asp-validation-for="Credential.Username"></div> </div><br /> <div class="form-group row"> <div class="col-3"> <label asp-for="Credential.Password"></label> </div> <div class="col-5"> <input type="password" asp-for="Credential.Password" class="form-control" /> </div> <div class="text-danger" asp-validation-for="Credential.Password"></div> </div> <div class="form-group row"> <div class="col-3"> <input type="submit" class="btn btn-primary" value="Login" /> </div> </div> </form> </div>
C# 控制器代码
using Identity.Pages.Account; using Microsoft.AspNetCore.Mvc; namespace Identity.Controller { [ApiController] public class LoginController : ControllerBase { [HttpPost] [Route("account/login")] public async Task<IActionResult> OnPostAsync([FromForm] Credential credential) { if (credential.Username == "badruddin" && credential.Password == "khan@123") { return Redirect("http://localhost:4200/"); } else { return NotFound("User Not Found"); } } } }
Angular service.service.ts代码
export class serviceService { check = true; constructor() { } loginUrl(): any { if(this.check == true){ this.check = false; return window.location.href = 'https://localhost:7139/account/login'; } } }
Angular resolver代码
export class ResolveResolver implements Resolve<boolean> { constructor(private service:MyserviceService){} resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> { this.service.loginUrl() return of(true); } }
Angular app-routing.ts代码
const routes: Routes = [ {path:'', component:AppComponent, pathMatch:'full', resolve: {redirection: ResolveResolver} } ];
当前问题
打开Angular应用时会重定向到C#登录页,输入正确凭据点击登录后,会短暂跳转到Angular应用,随后自动重定向回登录页。我希望验证通过后能停留在Angular应用中,目前未使用Cookie或JWT token。
解决方案
问题核心是登录成功后没有持久化用户已登录状态,Angular的resolver每次加载路由时都会触发检查,因为无状态标记,所以再次重定向到登录页。以下是分步解决方法:
1. 修改C#登录控制器,传递登录状态标记
登录成功后,给Angular的重定向URL添加loggedIn=true参数,明确告知用户已登录:
[HttpPost] [Route("account/login")] public async Task<IActionResult> OnPostAsync([FromForm] Credential credential) { if (credential.Username == "badruddin" && credential.Password == "khan@123") { // 重定向时携带登录状态参数 return Redirect("http://localhost:4200/?loggedIn=true"); } else { return NotFound("User Not Found"); } }
2. 改造Angular服务,持久化登录状态
使用localStorage保存登录状态(POC场景足够,生产环境建议用Cookie或JWT):
export class serviceService { constructor() { } // 检查是否已登录 isLoggedIn(): boolean { return localStorage.getItem('isLoggedIn') === 'true'; } // 设置登录状态 setLoggedIn(status: boolean): void { localStorage.setItem('isLoggedIn', status.toString()); } loginUrl(): void { if (!this.isLoggedIn()) { window.location.href = 'https://localhost:7139/account/login'; } } }
3. 修改Resolver,根据状态决定是否重定向
Resolver中先检查路由参数和本地存储状态,仅未登录时才跳转:
export class ResolveResolver implements Resolve<boolean> { constructor(private service: serviceService){} resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> { // 读取路由参数中的登录标记,设置本地存储 const loggedInParam = route.queryParamMap.get('loggedIn'); if (loggedInParam === 'true') { this.service.setLoggedIn(true); } // 未登录时跳转到登录页,否则正常加载路由 if (!this.service.isLoggedIn()) { this.service.loginUrl(); } return of(true); } }
4. 可选:添加登出功能(方便测试)
在Angular服务中添加登出方法,清除本地存储状态:
// 在serviceService中新增 logout(): void { localStorage.removeItem('isLoggedIn'); window.location.href = 'https://localhost:7139/account/login'; }
问题根源说明
之前的check变量是服务实例变量,页面刷新时Angular会重新创建服务实例,check重置为true,导致Resolver再次触发重定向。用localStorage可以跨页面刷新持久化状态,解决循环重定向问题。
内容的提问来源于stack exchange,提问作者Badruddin
相关产品推荐
相关产品推荐

