调用.Net API时如何解决邮递员中的401未授权错误

Posted

技术标签:

【中文标题】调用.Net API时如何解决邮递员中的401未授权错误【英文标题】:how to solve 401 unauthorized error in postman when calling a .Net API 【发布时间】:2022-01-07 15:39:29 【问题描述】:

我有一个 .net 核心 webapi 工作正常并用 swagger 进行了测试,该方法也设置为允许匿名访问,因此不需要身份验证。但是在使用 Postman 测试 POST 方法时,我总是收到 401 错误。感谢任何帮助!

【问题讨论】:

您的 POST 方法 API 是如何设置为允许匿名访问的?能否提供您的具体配置和 API 代码? 将示例 JWT 访问令牌的副本发布到问题中也会有所帮助。 ASP.NET Core 也确实提供了很好的 looing,可以让您很好地了解它失败的原因。 @Chaodeng 方法有 [allowanonymous] 保护,在启动文件中,在 launchSettings.json 中,"anonymousAuthentication": true, 【参考方案1】:

由于我不清楚你的具体代码实现,所以在这里写了一个demo,是一个从用户登录生成token到访问权限API的例子。可以参考一下,或许对你有一点帮助:

首先,打开 appsettings.json 文件并更改名为 Jwt 的部分:

"Jwt": 
    "Issuer": "testUser",
    "Audience": "user",
    "Key": "this is my custom Secret key for authnetication"
  

配置启动时启用JWT认证方案和swagger授权配置,整个代码如下:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using WebApplication129.Controllers.conf;

namespace WebApplication129

    public class Startup
    
        public Startup(IConfiguration configuration)
        
            Configuration = configuration;
        

        public IConfiguration Configuration  get; 

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        
            //services.AddSingleton<IConfiguration>(Configuration);
            services.AddAuthentication(opt => 
                opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            )
     .AddJwtBearer(options =>
     
         options.TokenValidationParameters = new TokenValidationParameters
         
             ValidateIssuer = true,
             ValidateAudience = true,
             ValidateLifetime = true,
             ValidateIssuerSigningKey = true,
             ValidIssuer = Configuration["Jwt:Issuer"],
             ValidAudience = Configuration["Jwt:Audience"],
             IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
         ;
     );
            services.AddControllers(options =>
            
                options.Conventions.Add(new GroupingByNamespaceConvention());
            );

            services.AddSwaggerGen(config =>
               
                config.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                
                    Description =
        "JWT Authorization header using the Bearer scheme. \r\n\r\n Enter 'Bearer' [space] and then your token in the text input below.\r\n\r\nExample: \"Bearer 12345abcdef\"",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey,
                    Scheme = "Bearer",
                    BearerFormat="JWT"
                );

                config.AddSecurityRequirement(new OpenApiSecurityRequirement()

    
        new OpenApiSecurityScheme
        
            Reference = new OpenApiReference
            
                Type = ReferenceType.SecurityScheme,
                Id = "Bearer"
            ,
            Scheme = "oauth2",
            Name = "Bearer",
            In = ParameterLocation.Header,

        ,
        new List<string>()
    
);


                var titleBase = "Test API";
                var description = "This is a Web API for Test operations";
                var TermsOfService = new Uri("https://xxxxxx");
                var License = new OpenApiLicense()
                
                    Name = "MIT"
                ;
                var Contact = new OpenApiContact()
                
                    Name = "Test",
                    Email = "Test@hotmail.com",
                    Url = new Uri("https://xxxxxx")
                ;

                config.SwaggerDoc("v1", new OpenApiInfo
                
                    Version = "v1",
                    Title = titleBase + " v1",
                    Description = description,
                    TermsOfService = TermsOfService,
                    License = License,
                    Contact = Contact
                );

                config.SwaggerDoc("v2", new OpenApiInfo
                
                    Version = "v2",
                    Title = titleBase + " v2",
                    Description = description,
                    TermsOfService = TermsOfService,
                    License = License,
                    Contact = Contact
                );

                var xmlFile = $"Assembly.GetExecutingAssembly().GetName().Name.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                config.IncludeXmlComments(xmlPath);
            );
        

       
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        
            if (env.IsDevelopment())
            
                app.UseDeveloperExceptionPage();
            
            app.UseSwagger();
            app.UseSwaggerUI(config =>
            
                config.SwaggerEndpoint("/swagger/v1/swagger.json", "Test v1");
                //config.SwaggerEndpoint("/swagger/v2/swagger.json", "Test v2");
            );
            app.UseHttpsRedirection();

            app.UseAuthentication();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            
                endpoints.MapControllers();
            );
        
    

如下登录并生成jwt部分。由于我没有将它与数据库一起使用,因此我自定义了一个用户:

型号:

public class Usuario
    
        public string NomeUsuario  get; set; 
        public string Senha  get; set; 
    

控制器:

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WebApplication129.Model;

namespace WebApplication129.Controllers.V1

    [Route("api/[controller]")]
    [ApiController]
    public class SegurancaController : Controller
    
        private IConfiguration _config;
        public SegurancaController(IConfiguration Configuration)
        
            _config = Configuration;
        
        [HttpPost]
        [Route("login")]
        public IActionResult Login([FromBody] Usuario loginDetalhes)
        
            bool resultado = ValidarUsuario(loginDetalhes);
            if (resultado)
            
                var tokenString = GerarTokenJWT();
                return Ok(new  token = tokenString );
            
            else
            
                return Unauthorized();
            
        
        private string GerarTokenJWT()
        
            var issuer = _config["Jwt:Issuer"];
            var audience = _config["Jwt:Audience"];
            var expiry = DateTime.Now.AddMinutes(120);
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
            var token = new JwtSecurityToken(issuer: issuer, audience: audience,
expires: expiry, signingCredentials: credentials);
            var tokenHandler = new JwtSecurityTokenHandler();
            var stringToken = tokenHandler.WriteToken(token);
            return stringToken;
        
        private bool ValidarUsuario(Usuario loginDetalhes)
        
            if (loginDetalhes.NomeUsuario == "TestName" && loginDetalhes.Senha == "TestPwd")
            
                return true;
            
            else
            
                return false;
            
        
    

测试和验证 API:

 [ApiController]
[Route("api/v1/[controller]")]
public class HomeController : ControllerBase

    /// <summary>
    /// Add the description information you need    
    /// </summary>
    /// 
    /// 
    [Route("test")]
   [HttpGet]
    
    public string Test( int userID)
    
        return "v1 test";
    

    [Route("list_data")]
    [HttpGet]
    [Authorize]
    public Object  Data()
    
        User user = new User();
        user.id = 1;
        user.userName = "Test";
        user.email = "test@xxx.com";
        user.address = "testAddress";

        return user;
    


上面展示了两个API,一个需要授权,一个不需要授权才能访问。

结果:

【讨论】:

感谢您提供详细示例。感谢这一点,尽管我的错误是在使用 Postman 时没有包含正确的 JWT 不记名令牌

以上是关于调用.Net API时如何解决邮递员中的401未授权错误的主要内容,如果未能解决你的问题,请参考以下文章

浏览器没有响应,但在邮递员中得到 401

当我一直得到 401 时,如何使用标题删除 axios?

ASP.NET Core API 在从 React 客户端调用时返回 401

如何解决使用redux的react js中的401错误。?

.net 核心允许在使用 CORS 时发回错误 401(而不是零)

邮递员使用 JWT 进行授权调用时无法获得任何响应