Asp.net core 在Asp.NET Core 3.0 API控制器中,当方法未使用Authorize修饰时,User.Identity.Name在JWT中为空

Asp.net core 在Asp.NET Core 3.0 API控制器中,当方法未使用Authorize修饰时,User.Identity.Name在JWT中为空,asp.net-core,.net-core,jwt,Asp.net Core,.net Core,Jwt,我在.NETCore3.1中有一个WebAPI项目,并添加了JwT身份验证。 身份验证和授权工作得很好,但我需要在每个请求中获取用户ID。当使用Authorize属性修饰该方法时,效果很好 [HttpGet] [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] public IEnumerable<WeatherForecast> Get() {

我在.NETCore3.1中有一个WebAPI项目,并添加了JwT身份验证。 身份验证和授权工作得很好,但我需要在每个请求中获取用户ID。当使用Authorize属性修饰该方法时,效果很好

[HttpGet]
    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
    public IEnumerable<WeatherForecast> Get()
    {
        string user = User.Identity.Name; //Get a value
        //Do something
    }
[HttpGet]
[授权(AuthenticationSchemes=JwtBearerDefaults.AuthenticationScheme)]
公共IEnumerable Get()
{
字符串user=user.Identity.Name;//获取一个值
//做点什么
}
但是,我有一些不需要身份验证的方法,但是如果经过身份验证的用户发出请求,我希望获得userId,但在这种情况下,user.Identity.Name始终为null

[HttpGet]
    public IEnumerable<WeatherForecast> Get()
    {
        string user = User.Identity.Name; //null
        //Do somwthing
    }
[HttpGet]
公共IEnumerable Get()
{
字符串user=user.Identity.Name;//null
//做些事
}
我在statur文件中的配置是:

private void ConfigureJwt(IServiceCollection services)
    {
        //Add Auth scheme
        services.AddAuthorization(options =>
        {
            var defaultAuthorizationPolicyBuilder = new Microsoft.AspNetCore.Authorization.AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme);
            defaultAuthorizationPolicyBuilder = defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
            options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
        });

        AuthSettings authSettings = Configuration.GetSection("AuthSettings").Get<AuthSettings>();
        JwtIssuerOptions jwtIssuerOptions = Configuration.GetSection("JwtIssuerOptions").Get<JwtIssuerOptions>();

        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 = jwtIssuerOptions.Issuer,
                ValidAudience = jwtIssuerOptions.Audience,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(authSettings.SecretKey))
            };
            options.Events = new JwtBearerEvents
            {
                OnTokenValidated = context =>
                {
                    //When method is no decorated with Authorize, it not working
                    var userId = int.Parse(context.Principal.Identity.Name);
                    return System.Threading.Tasks.Task.CompletedTask;
                }
            };
        });

        services.AddTransient<ITokenService, TokenService>(x =>
        {
            return new TokenService(Configuration);
        });
    } 
private void ConfigureJwt(IServiceCollection服务)
{
//添加身份验证方案
services.AddAuthorization(选项=>
{
var defaultAuthorizationPolicyBuilder=new Microsoft.AspNetCore.Authorization.AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme);
defaultAuthorizationPolicyBuilder=defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
options.DefaultPolicy=defaultAuthorizationPolicyBuilder.Build();
});
AuthSettings AuthSettings=Configuration.GetSection(“AuthSettings”).Get();
JWTISSUSEROPTIONS JWTISSUSEROPTIONS=Configuration.GetSection(“JWTISSUSEROPTIONS”).Get();
services.AddAuthentication(opt=>
{
opt.DefaultAuthenticateScheme=JwtBearerDefaults.AuthenticationScheme;
opt.DefaultChallengeScheme=JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(选项=>
{
options.TokenValidationParameters=新的TokenValidationParameters
{
validateisuer=true,
ValidateAudience=true,
ValidateLifetime=true,
ValidateSuersigningKey=true,
ValidIssuer=jwtIssuerOptions.Issuer,
Validudience=jwtIssuerOptions.观众,
IssuerSigningKey=new-SymmetricSecurityKey(Encoding.UTF8.GetBytes(authSettings.SecretKey))
};
options.Events=newjwtbearerevents
{
OnTokenValidated=上下文=>
{
//当方法未使用Authorize修饰时,它将不起作用
var userId=int.Parse(context.Principal.Identity.Name);
返回System.Threading.Tasks.Task.CompletedTask;
}
};
});
services.AddTransient(x=>
{
返回新的令牌服务(配置);
});
} 
令牌服务类:

public class TokenService : ITokenService
{
    IConfiguration configuration = null;
    AuthSettings authSettings = null;
    public TokenService(IConfiguration _configuration)
    {
        configuration = _configuration;
        authSettings = configuration.GetSection("AuthSettings").Get<AuthSettings>();
    }

    public string GenerateAccessToken(IEnumerable<Claim> claims, ref JwtIssuerOptions jwtIssuerOptions)
    {
        //var authSettings = configuration.GetSection(nameof(AuthSettings));
        //var authSettings = configuration.GetSection("EmailSettings").Get<AuthSettings>();
        jwtIssuerOptions = configuration.GetSection("JwtIssuerOptions").Get<JwtIssuerOptions>();

        var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(authSettings.SecretKey));
        var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);

        var tokeOptions = new JwtSecurityToken (
            issuer: jwtIssuerOptions.Issuer,
            audience: jwtIssuerOptions.Audience,
            claims: claims,
            expires: jwtIssuerOptions.Expiration,
            //expires: DateTime.Now.AddMinutes(5),
            signingCredentials: signinCredentials
        );

        var tokenString = new JwtSecurityTokenHandler().WriteToken(tokeOptions);
        return tokenString;
    }

    public string GenerateRefreshToken()
    {
        var randomNumber = new byte[32];
        using (var rng = RandomNumberGenerator.Create())
        {
            rng.GetBytes(randomNumber);
            return Convert.ToBase64String(randomNumber);
        }
    }
    public ClaimsPrincipal GetPrincipalFromExpiredToken(string token)
    {
        TokenValidationParameters tokenValidationParameters = GetValidationParameters();

        var tokenHandler = new JwtSecurityTokenHandler();
        SecurityToken securityToken;
        var principal = tokenHandler.ValidateToken(token, tokenValidationParameters, out securityToken);
        var jwtSecurityToken = securityToken as JwtSecurityToken;
        if (jwtSecurityToken == null || !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase))
            throw new SecurityTokenException("Invalid token");

        return principal;
    }

    private TokenValidationParameters GetValidationParameters()
    {
        var tokenValidationParameters = new TokenValidationParameters
        {
            ValidateAudience = false, //you might want to validate the audience and issuer depending on your use case
            ValidateIssuer = false,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(authSettings.SecretKey)),
            ValidateLifetime = false //here we are saying that we don't care about the token's expiration date
        };
        return tokenValidationParameters;
    }
}
公共类令牌服务:ITokenService
{
IConfiguration配置=null;
AuthSettings AuthSettings=null;
公共令牌服务(IConfiguration\u配置)
{
配置=_配置;
authSettings=configuration.GetSection(“authSettings”).Get();
}
公共字符串GenerateAccessToken(IEnumerable声明,参考JWTISSUPEROPTIONS JWTISSUPEROPTIONS)
{
//var authSettings=configuration.GetSection(nameof(authSettings));
//var authSettings=configuration.GetSection(“EmailSettings”).Get();
jwtIssuerOptions=configuration.GetSection(“jwtIssuerOptions”).Get();
var secretKey=new SymmetricSecurityKey(Encoding.UTF8.GetBytes(authSettings.secretKey));
var signinCredentials=新的签名凭证(secretKey,SecurityAlgorithms.HmacSha256);
var tokeOptions=新的JwtSecurityToken(
发卡机构:jwtIssuerOptions。发卡机构,
观众:jwtIssuerOptions。观众,
索赔:索赔,
过期:jwtIssuerOptions.Expiration,
//过期:DateTime.Now.AddMinutes(5),
签名凭据:签名凭据
);
var tokenString=new JwtSecurityTokenHandler().WriteToken(tokeOptions);
返回令牌字符串;
}
公共字符串GenerateRefreshToken()
{
var randomNumber=新字节[32];
使用(var rng=RandomNumberGenerator.Create())
{
rng.GetBytes(随机数);
返回Convert.tobase64字符串(随机数);
}
}
公共请求权SPRINCIPAL GetPrincipalFromeExpiredToken(字符串令牌)
{
TokenValidationParameters TokenValidationParameters=GetValidationParameters();
var tokenHandler=new JwtSecurityTokenHandler();
SecurityToken SecurityToken;
var principal=tokenHandler.ValidateToken(令牌、tokenValidationParameters、out securityToken);
var jwtSecurityToken=作为jwtSecurityToken的securityToken;
if(jwtSecurityToken==null | |!jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256,StringComparison.InvariantCultureIgnoreCase))
抛出新的SecurityTokenException(“无效令牌”);
返还本金;
}
私有令牌验证参数GetValidationParameters()
{
var tokenValidationParameters=新的tokenValidationParameters
{
validateudience=false,//根据您的用例,您可能希望验证受众和发行者
validateisuer=false,
ValidateSuersigningKey=true,
IssuerSigningKey=new-SymmetricSecurityKey(Encoding.UTF8.GetBytes(authSettings.SecretKey)),
ValidateLifetime=false//这里我们说的是我们不关心令牌的过期日期
};
返回tokenValidationParameters;
}
}
授权控制器

    [HttpPost, Route("login")]
    public async Task<IActionResult> Login([FromBody] LoginModel loginModel)
    {
        if (loginModel == null)
            return BadRequest("Invalid client request");

        var sessionInfo = await userBo.LoginUser(loginModel);
        if (sessionInfo == null)
            return Unauthorized();

        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, sessionInfo.User.BusinessEntityId.ToString()),
            new Claim(ClaimTypes.Role, sessionInfo.User.RoleCode)
        };

        JwtIssuerOptions tokeOptions = null;
        var accessToken = tokenService.GenerateAccessToken(claims, ref tokeOptions);
        var refreshToken = tokenService.GenerateRefreshToken();

        await tokenBo.SaveToken(
            new Token()
            {
                BusinessEntityId = sessionInfo.Person.BusinessEntityId,
                RefreshToken = refreshToken,
                RefreshTokenExpiryTime = tokeOptions.Expiration
            }
        );

        sessionInfo.TokenInfo = new TokenInfo()
        {
            AccessToken = accessToken,
            RefreshToken = refreshToken
        };
        return Ok(sessionInfo);
    }
}
[HttpPost,路由(“登录”)]
公共异步任务登录([FromBody]LoginModel LoginModel)
{
如果(逻辑)
        app.Use(async (context, next) =>
        {
            // you could get from token or get from session. 
            string token = context.Request.Headers["Authorization"];
            if (!string.IsNullOrEmpty(token))
            {
                var tok = token.Replace("Bearer ", "");
                var jwttoken = new JwtSecurityTokenHandler().ReadJwtToken(tok);

                 var jti = jwttoken.Claims.First(claim => claim.Type == ClaimTypes.Name).Value;
                context.Items.Add("Username", jti);
            }
    
            await next();

        });
        object value;
        ControllerContext.HttpContext.Items.TryGetValue("Username", out value);

        var username = value.ToString();