我是第一次使用授權制作應用程式,我在這里遇到了一些問題。我正在使用 angular asp.net 默認身份驗證,我的背景關系繼承如下所示:
public class CoffeeContext : IdentityDbContext<User, UserRole, int>
UserRole 是一個從 IdentityRole < int > 繼承而來的空類。User 也是從 IdentityUser < int > 繼承的空類。
這是我的 UsersControllerClass 的樣子:
[ApiController]
[Route("users")]
public class UsersController : ControllerBase
{
private readonly SignInManager<User> _signInManager;
private readonly UserManager<User> _userManager;
public UsersController(SignInManager<User> signInManager, UserManager<User> userManager)
{
_signInManager = signInManager;
_userManager = userManager;
}
[HttpPost]
[Route("Login")]
public async Task<IActionResult> Login(UserDto userDto)
{
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(userDto.Email, userDto.Password, false, false);
if (result.Succeeded)
{
return Ok();
}
else
{
return BadRequest();
}
}
return Ok();
}
[HttpPost]
[Route("Register")]
public async Task<IActionResult> Register(UserDto userDto)
{
if (ModelState.IsValid)
{
var user = new User() {UserName = userDto.Email, Email = userDto.Email};
var result = await _userManager.CreateAsync(user, userDto.Password);
if (result.Succeeded)
{
return Ok();
}
}
return BadRequest();
}
[HttpGet]
[Route("Logout")]
public async Task<IActionResult> Logout()
{
if (ModelState.IsValid)
{
await _signInManager.SignOutAsync();
}
return Ok();
}
}
UserDto 有 2 個屬性:字串電子郵件、字串密碼。我有幾個具有 userId 屬性的類。例如食譜:
[ApiController]
[Route("Recipes")]
public class RecipesController : ControllerBase
{
private readonly IRecipeService _recipeService;
private readonly Microsoft.AspNetCore.Identity.UserManager<User> _userManager;
public RecipesController(IRecipeService recipeService, Microsoft.AspNetCore.Identity.UserManager<User> userManager)
{
_recipeService = recipeService;
_userManager = userManager;
}
[HttpPost]
public async Task<IActionResult> CreateRecipe(RecipeDto recipeDto)
{
var userId = IdentityExtensions.GetUserId(User.Identity);
recipeDto.UserId = int.Parse(userId);
await _recipeService.CreateRecipe(recipeDto);
return CreatedAtAction(nameof(GetRecipeById), new { Id = recipeDto.Id }, recipeDto);
}
如您所見,我通過 IdentityExtension.GetUserId(); 獲取 userId;
當我使用 swagger 測驗此方法時(首先使用來自用戶控制器的登錄方法,然后使用 CreateRecipe),一切正常,它獲取當前登錄用戶的正確 id。問題是當我嘗試通過帶有角度的前端使用該方法時。這是我的登錄模塊的樣子:
export class LoginComponent implements OnInit {
userForm! : FormGroup;
user! : LoginModel;
subbmited = false;
constructor(private formBuilder: FormBuilder, private userService: UserService) { }
ngOnInit(){
this.userForm = this.formBuilder.group({
email: ['', Validators.required],
password: ['', Validators.required]
})
}
get Email(){
return this.userForm.get('email');
}
get Password(){
return this.userForm.get('password');
}
onSubmit(){
this.user = this.userForm.value;
this.userService.LogIn(this.user).subscribe(res => { console.log(res)});
}
userService,loginComponent 傳遞的值是正確的(注冊方法作業正常):
export class UserService {
readonly ApiUrl = "https://localhost:44331/users"
constructor(private http: HttpClient) { }
LogIn(loginModel: LoginModel){
return this.http.post(this.ApiUrl '/Login', loginModel, this.generateHeaders());
}
Register(loginModel: RegisterModel){
return this.http.post(this.ApiUrl '/Register', loginModel, this.generateHeaders());
}
private generateHeaders = () => {
return {
headers: new HttpHeaders({
"Content-Type": "application/json",
}),
};
};
}
這就是我添加食譜的方式:
addRecipe(){
var val = {
id:this.RecipeId,
name:this.RecipeName,
recipeBody:this.RecipeBody,
userId: 0,
intendedUse:this.RecipeIntentedUse,
coffeeId:this.RecipeCoffeeId
};
this.service.createRecipe(val).subscribe(res=>{
alert(res.toString());
});
}
來自輸入的值是正確的,我將 userId 設定為 0,因為無論如何它都會在后端被替換(或者至少我認為它應該被替換)。最后我得到Http status: 500, Value can not be null。當我通過除錯檢查 userId 值在后端的樣子時:

正如您所看到的,當前登錄用戶的 ID 為 null,我想這意味著沒有登錄用戶。我該如何解決?
編輯: recipe.component.ts:
import { Component, OnInit } from '@angular/core';
import { SharedService } from '../shared/shared.service';
@Component({
selector: 'app-recipe',
templateUrl: './recipe.component.html',
styleUrls: ['./recipe.component.css']
})
export class RecipeComponent implements OnInit {
ModalTitle:string="";
recipe: any;
ActiveAddEdditRecipe:boolean=false;
constructor(private service:SharedService) { }
RecipeList: any = [];
ngOnInit(): void {
this.refreshRecipeList();
}
refreshRecipeList(){
this.service.getRecipes().subscribe(data => {
this.RecipeList=data;
})
}
addClick(){
this.recipe={
id:0,
name:"",
recipeBody:"",
userId:"",
intendedUse:"",
coffeeId:""
}
this.ModalTitle="Add recipe";
this.ActiveAddEdditRecipe=true;
}
editClick(recipeEdit: any){
this.recipe=recipeEdit;
this.ModalTitle="Edit recipe";
this.ActiveAddEdditRecipe=true;
}
closeClick(){
this.ActiveAddEdditRecipe=false;
this.refreshRecipeList();
}
deleteClick(recipeDelete: any){
this.service.deleteRecipe(recipeDelete).subscribe(data => this.refreshRecipeList());
}
}
html:
<button type="button" class="btn btn-primary float-right m-2" data-bs-toggle="modal" data-bs-target="#exampleModal"
(click)="addClick()"
data-backdrop="static"
data-keyboard="false">
Add Coffee
</button>
<div class="modal" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">{{ModalTitle}}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"
(click)="closeClick()" (click)="refreshRecipeList()">
</button>
</div>
<div class="modal-body">
<app-add-edit-recipe [recipe]="recipe" *ngIf="ActiveAddEdditRecipe"></app-add-edit-recipe>
</div>
</div>
</div>
</div>
<div class="wrapper">
<header>
<h1>Recipe</h1>
</header>
<section class="columns" *ngFor="let recipe of RecipeList">
<div class="column">
<h2>{{recipe.name}}</h2>
<p>{{recipe.recipeBody}}</p>
</div>
</section>
</div>
并添加EditRecipeComponent
Component({
selector: 'app-add-edit-recipe',
templateUrl: './add-edit-recipe.component.html',
styleUrls: ['./add-edit-recipe.component.css']
})
export class AddEditRecipeComponent implements OnInit {
@Input() recipe: any;
RecipeId!: number ;
RecipeName: string="";
RecipeBody : string="";
RecipeUserId : number = 0;
RecipeIntentedUse: string ="";
RecipeCoffeeId: string ="";
CoffeeList: any[] = [];
constructor(private service : SharedService) { }
ngOnInit(): void {
this.RecipeId = this.recipe.id;
this.RecipeName = this.recipe.name;
this.RecipeBody = this.recipe.recipeBody;
this.RecipeUserId = this.recipe.userId;
this.RecipeIntentedUse = this.recipe.intendedUse;
this.RecipeCoffeeId = this.recipe.coffeeId;
this.getCoffeesList();
}
addRecipe(){
var val = {
id:this.RecipeId,
name:this.RecipeName,
recipeBody:this.RecipeBody,
userId: 1,
intendedUse:this.RecipeIntentedUse,
coffeeId:this.RecipeCoffeeId
};
this.service.createRecipe(val).subscribe(res=>{
alert(res.toString());
});
}
updateRecipe(){
var val = {
id:this.RecipeId,
name:this.RecipeName,
recipeBody:this.RecipeBody,
userId:this.RecipeUserId,
intendedUse:this.RecipeIntentedUse,
coffeeId:this.RecipeCoffeeId
};
this.service.updateRecipe(val).subscribe(res=>{
alert(res.toString());
});
}
getCoffeesList(){
this.service.getCoffees().subscribe(data => {
this.CoffeeList = data;
})
}
}
<div class ="col-sm-10">
<input type="text" class="form-control" [(ngModel)]="RecipeName" placeholder="Enter recipe name">
<input type="text" class="form-control" [(ngModel)]="RecipeBody" placeholder="Enter recipe text">
<select type="text" class="form-control" [(ngModel)]="RecipeIntentedUse">
<option value="" disabled selected>Intended Use</option>
<option value="Espresso">Espresso</option>
<option value="Aeropress">Aeropress</option>
<option value="FrenchPress">FrenchPress</option>
<option value="Chemex">Chemex</option>
<option value="Dripper">MediDripperum</option>
<option value="MokaPot">MokaPot</option>
</select>
<select type="text" class="form-control" [(ngModel)]="RecipeCoffeeId">
<option value="" disabled selected>Select coffee</option>
<option *ngFor="let coffee of CoffeeList"
[value]="coffee.id" >{{coffee.name}}</option>
</select>
</div>
添加更新
uj5u.com熱心網友回復:
您的logIn()功能未正確實作。它不發送任何身份驗證標頭,這就是它不起作用的原因。我不明白你的代碼發生了什么,但假設你的后端作業正常,我會這樣做:
我認為您應該做的是創建一個 Auth Interceptor 并在您的 Angular 應用程式上設定所有 Http 請求以包含您的授權標頭。試試這個(假設你已經使用了 BasicAuth):在你的login.ts模塊上
export class LoginComponent implements OnInit {
userForm! : FormGroup;
email : any;
password: any;
encodedValues: any;
subbmited = false;
constructor(private formBuilder: FormBuilder, private userService: UserService) { }
ngOnInit(){
this.userForm = this.formBuilder.group({
email: ['', Validators.email],
password: ['', Validators.required]
})
}
getEmail(event:any){
this.email = event.target.value;
}
getPassword(event:any){
this.password = event.target.value;
}
onSubmit(){
this.http.post("YOUR API ENDPOINT", this.userForm.getRawValue()).subscribe((res:any)=>{
this.encodedValues = btoa(this.email ":" this.password),
sessionStorage.setItem("encodedValues", this.encodedValues)
})
在您的login.html檔案中,更改您的輸入以包含事件更改:
<input type="text" formControlName="email" (change)="getEmail($event)">
<input type="text" formControlName="password" (change)="getPassword($event)">
這會將您的身份驗證詳細資訊存盤在您的瀏覽器存盤中,并將作為 AuthInterceptor 的標頭傳遞
生成一個身份驗證攔截器:
ng g interceptor AuthInterceptor
在您的AuthInterceptor檔案中,添加此項以檢索您的身份驗證詳細資訊并將它們作為標頭傳遞給每個:
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
const token = localStorage.getItem("encodedValues")
request = request.clone({
setHeaders: {
Authorization: `Basic ${token}`
}
});
return next.handle(request);
}
}
export const authInterceptorProviders = [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
];
最后,在添加食譜時,請分享整個內容,.ts以便我可以使用一些東西
編輯
您的service.ts檔案和RecipeComponent檔案看起來正確。
如果您如上所述添加了 AuthInterceptor,則轉到您的 app.module.ts 并將其添加到您的提供程式中。
providers: [ { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true } ],
這將設定所有 HTTP 請求的標頭
那應該作業
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/366419.html
