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