.Net6 WebApi + JWTBearer身份认证的简单实现

.Net6 WebApi + JWTBearer身份认证的简单实现

开发环境

  • VS2022
  • .Net6 WebApi
  • using Microsoft.AspNetCore.Authentication.JwtBearer;
    using Microsoft.IdentityModel.Tokens;

配置文件

在 appsettings.json 文件添加

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "JWT": {
    "SecretKey": "[email protected]",
    "Issuer": "Apple",
    "ExpiresMinutes": 120,
    "Audience": "customer"
  }
}

实体类

TokenParameter.cs

    public class TokenParameter
    {
        public string Issuer { get; set; }
        public string Audience { get; set; }
        public string SecretKey { get; set; }
        public double ExpiresMinutes { get; set; }
    }

配置类

AppSettings.cs

public static class AppSettings
{
    public static TokenParameter tokenParameter { get; set; }

    public static void Init(IConfiguration configuration)
    {
        tokenParameter = new TokenParameter();
        configuration.Bind("JWT", tokenParameter);
    }
}

Program类

Program.cs

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json;
using System.Text;
using System.Text.Json.Serialization;

var builder = WebApplication.CreateBuilder(args);

var config = builder.Configuration;
// Add services to the container.
AppSettings.Init(config);

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
    options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = "请输入token ,格式为 Bearer xxxxx.xxxxx.xxxxx",
        Name = "Authorization",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.Http,
        BearerFormat = "JWT",
        Scheme = "Bearer"
    });
    options.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type=ReferenceType.SecurityScheme,
                    Id="Bearer"
                }
            } , new string[]{}
        }
    });
});

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters()
    {
        ValidateIssuer = true,
        ValidIssuer = AppSettings.tokenParameter.Issuer,
        ValidateAudience = true,
        ValidAudience = AppSettings.tokenParameter.Audience,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(AppSettings.tokenParameter.SecretKey))
    };
    options.Events = new JwtBearerEvents
    {
        OnChallenge = context =>
        {
            context.HandleResponse();
            var payload = JsonConvert.SerializeObject(new { Code = "401", Message = "很抱歉,您无权访问该接口" });
            context.Response.StatusCode = StatusCodes.Status200OK;
            context.Response.ContentType = "application/json";
            context.Response.WriteAsync(payload);
            return Task.CompletedTask;
        }
    };
});
builder.Services.AddTransient<ITokenService, TokenService>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseAuthentication();

app.UseAuthorization();

app.MapControllers();

app.Run();

token接口和实现

ITokenService.cs 接口类

    public interface ITokenService
    {
        string GetToken();
    }

TokenService.cs 实现类

    public class TokenService : ITokenService
    {
        public string GetToken()
        {
            var claims = new[]
            {
                new Claim("Id","10001"),
                new Claim("Name","Admin")
            };

            var key = AppSettings.tokenParameter.SecretKey;

            var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));

            var algorithm = SecurityAlgorithms.HmacSha256;

            var signature = new SigningCredentials(secretKey, algorithm);

            var expires = Convert.ToDouble(AppSettings.tokenParameter.ExpiresMinutes);

            var token = new JwtSecurityToken(
                AppSettings.tokenParameter.Issuer,
                AppSettings.tokenParameter.Audience,
                claims,
                DateTime.Now,
                DateTime.Now.AddDays(expires),
                signature
                );

            var jwtToken = new JwtSecurityTokenHandler().WriteToken(token);

            return jwtToken;
        }
    }

控制器类

TokenController.cs 中Login()获取token的值

    [ApiController]
    [Route("api/[controller]/[action]")]
    public class TokenController : ControllerBase
    {
        private readonly ITokenService _tokenService;
        public TokenController(ITokenService tokenService)
        {
            _tokenService = tokenService;
        }
        [HttpGet(Name = "Login")]
        public IActionResult Login()
        {
            if (!ModelState.IsValid)
            {
                return BadRequest("Name or Password can not be Empty");
            }

            var token = _tokenService.GetToken();

            return Ok(token);
        }
    }

业务调用

WeatherForecastController.cs 中的方法加上[Authorize]特性

    [ApiController]
    [Route("api/[controller]/[action]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet(Name = "GetWeatherForecast")]
        [Authorize]
        public IEnumerable<WeatherForecast> Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }

你可能感兴趣的:(后端,.netcore,WebApi,.netcore,.net,restful,visualstudio)