JWT身份验证ASP.NET Core MVC应用程序

时间:2019-02-06 17:40:54

标签: asp.net-mvc asp.net-core jwt

我已经看到了许多有关如何在Angular,React,Vue等客户端上使用JWT身份验证的示例,但是找不到在ASP.NET Core(特别是2.2)Web App Mvc中使用JWT身份验证的任何示例。

有人对此有任何示例或建议吗?

谢谢

3 个答案:

答案 0 :(得分:0)

您可以使用this boilerplate来了解如何使用.Net Core实现JWT令牌化。在项目中,您可以找到JWT,Swagger和EF功能。

答案 1 :(得分:0)

将以下代码添加到启动

public void ConfigureServices(IServiceCollection services)
    {

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = Configuration["Issuer"],
                    ValidAudience = Configuration["Audience"],
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["SigningKey"]))
                };
            });

    }


 public void Configure(IApplicationBuilder app, IHostingEnvironment env,, ILoggerFactory loggerFactory)
  {
   app.UseAuthentication();

}

AccountController中的登录操作代码

[Route("api/[controller]")]
public class AccountController : Controller
{
[AllowAnonymous]
[HttpPost]
[Route("login")]
public IActionResult Login([FromBody]LoginViewModel loginViewModel)
{

    if (ModelState.IsValid)
    {
        var user = _userService.Authenticate(loginViewModel);


        var claims = new[]
        {
                new Claim(JwtRegisteredClaimNames.Sub, loginViewModel.Username),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
                };

        var token = new JwtSecurityToken
                    (
                        issuer: _configuration["Issuer"],
                        audience: _configuration["Audience"],
                        claims: claims,
                        expires: DateTime.UtcNow.AddDays(10),
                        notBefore: DateTime.UtcNow,
                        signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["SigningKey"])),
                             SecurityAlgorithms.HmacSha256)
                    );

        return Ok(new
        {
            access_token = new JwtSecurityTokenHandler().WriteToken(token),
            expires_in = (int)token.ValidTo.Subtract(DateTime.UtcNow).TotalSeconds,// TimeSpan.FromTicks( token.ValidTo.Ticks).TotalSeconds,
            sub = loginViewModel.Username,
            name = loginViewModel.Username,
            fullName = user.FullName,
            jobtitle = string.Empty,
            phone = string.Empty,
            email = user.EmailName,

        });
    }
}

}

答案 2 :(得分:0)

  

您可以基于nuget包JWT 3.0.3使用此类。

using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using Newtonsoft.Json;
using System;

namespace Common.Utils
{
  public class JwtToken
  {
    private IJwtEncoder encoder;
    private IJwtDecoder decoder;

    /// <remarks>
    /// This requires a key value randomly generated and stored in your configuration settings. 
    /// Consider that it is a good practice use keys as at least long as the output digest bytes 
    /// length produced by the hashing algorithm used. Since we use an HMAC-SHA-512 algorithm, 
    /// then we can provide it a key at least 64 bytes long.
    /// <see cref="https://tools.ietf.org/html/rfc4868#page-7"/>
    /// </remarks>
    public string SecretKey { get; set; } 

    public JwtToken()
    {
        IJwtAlgorithm algorithm = new HMACSHA512Algorithm();
        IJsonSerializer serializer = new JsonNetSerializer();
        IDateTimeProvider datetimeProvider = new UtcDateTimeProvider();
        IJwtValidator validator = new JwtValidator(serializer, datetimeProvider);
        IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();

        encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
        decoder = new JwtDecoder(serializer, validator, urlEncoder);
        SecretKey = "";
    }

    public JwtToken(string secretKey) : this()
    {
        SecretKey = secretKey;
    }

    public bool IsTokenValid(string token)
    {
        return !string.IsNullOrWhiteSpace(DecodeToken(token));
    }

    public string GetToken(object payload)
    {
        try
        {
            return encoder.Encode(payload, SecretKey);
        }
        catch (Exception)
        {
            return encoder.Encode(new DataModel(payload), SecretKey);
        }
    }

    public string DecodeToken(string token)
    {
        try
        {
            if (string.IsNullOrWhiteSpace(token) || token == "null")
            {
                return null;
            }
            return decoder.Decode(token, SecretKey, true);
        }
        catch (TokenExpiredException)
        {
            return null;
        }
        catch (SignatureVerificationException)
        {
            return null;
        }
    }

    public T DecodeToken<T>(string token) where T : class
    {
        try
        {
            if (string.IsNullOrWhiteSpace(token))
            {
                return null;
            }
            return decoder.DecodeToObject<T>(token, SecretKey, true);
        }
        catch (TokenExpiredException)
        {
            return null;
        }
        catch (SignatureVerificationException)
        {
            return null;
        }
        catch (Exception)
        {
            var data = decoder.DecodeToObject<DataModel>(token, SecretKey, true).Data;
            return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(data));
        }
    }
  }

  public class DataModel
  {
    public DataModel(object data)
    {
        Data = data;
    }
    public object Data { get; set; }
  }
}
  

然后在您的StartupConfigure方法中设置jwt中间件   用于检查每个请求的身份验证状态:

app.Use((context, next) =>
        {

            // verify app access token if not another service call
            var appAccessToken = context.Request.Headers["Authorization"];
            if (appAccessToken.Count == 0)
            {
                context.Items["User"] = null;
            }
            else
            {
                var token = appAccessToken.ToString().Replace("Bearer ", "");
                var jwtToken = new JwtToken(config.JwtTokenSecret); //you need a secret (with requirements specified above) in your configuration (db, appsettings.json)
                if (string.IsNullOrWhiteSpace(token) || !jwtToken.IsTokenValid(token))
                {
                    context.Response.StatusCode = 401;
                    return Task.FromResult(0);
                }

                dynamic user = jwtToken.DecodeToken<dynamic>(token);

                var cachedToken = cache.Get(user.Id);  //you need some cache for store your token after login success and so can check against
                if (cachedToken == null || cachedToken.ToString() != token)
                {
                    context.Response.StatusCode = 401;
                    return Task.FromResult(0);
                }

                context.Items["User"] = new Dictionary<string, string>() {
                        { "FullName",user.Name?.ToString()},
                        { "FirstName",user.FirstName?.ToString()},
                        { "LastName",user.LastName?.ToString()},
                        { "Role",user.Role?.ToString()},
                        { "Email",user.Email?.ToString()}
                    };
            }
            return next();
        });
  

最后,您需要生成令牌并在之后返回它   身份验证:

    [AllowAnonymous]
    public IActionResult Login(string username, string password)
    {
        User user = null; //you need some User class with the structure of the previous dictionary
        if (checkAuthenticationOK(username, password, out user)) //chackAuthenticationOk sets the user against db data after a succesfull authentication
        {
           var token = new JwtToken(_config.JwtTokenSecret).GetToken(user);  //_config is an object to your configuration
           _cache.Set(user.id, token);  //store in the cache the token for checking in each request
           return Ok(token);
        }

        return StatusCode(401, "User is not authorized");
    }