我想拦截每个进入 api 的网络请求,在每个请求期间我想调用一个我编写的函数,它会告诉我用户有一个有效的未过期的许可证 key 。我需要做的几件事是能够识别用户,我可以通过打开 JWT token 来做到这一点我需要访问该 token ,我还需要能够从我的一个类中调用方法,即已经注册使用 autofac 进行注入(inject)。我知道我可以使用 Action 过滤器和中间件,但我没有太多使用这些的经验,我正在寻找最好的方法来做到这一点,甚至可以给我一些例子。哦,我还必须能够知道路线,有几个 API 方法可以免除此检查。如果检查感觉我显然要抛出请求,可能会抛出 401 错误或其他东西。
最佳答案
我强烈推荐 Neil Cummings 的 Udemy 类(class) Build an App with ASPNET Core and Angular From Scratch
sample solution包括 MIT 许可证。
这个 28 小时的类(class)和相关解决方案利用:
- 用于身份验证的 JWT token 和 Microsoft.AspNetCore.Identity
- IAsyncActionFilter 到:
- 拦截网络请求
- 阅读用户声明
- 解决来自 Microsoft.Extensions.DependencyInjection
以下部分与您要完成的工作直接相关:
3.26 创建具体的授权库和注册方法
3.27 创建登录存储库方法
3.29 在我们的 Auth Controller 中创建 Register 方法
3.32 token 认证
客户端将 token 发送到服务器。服务器不使用数据库来验证用户,它验证 token 本身。
3.33 在API中创建登录方法
在此处将声明添加到 token :
AuthController.cs
public class AuthController : ControllerBase
{
[HttpPost("login")]
public async Task<IActionResult> Login(UserForLoginDto userForLoginDto)
{
…
return Ok(new {
token = GenerateJwtToken(appUser).Result,
user = userToReturn});}
}
private async Task<string> GenerateJwtToken(User user)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.UserName)
};
var roles = await _userManager.GetRolesAsync(user);
foreach (var role in roles)
{
claims.Add(new Claim(ClaimTypes.Role, role));
}
var key = new SymmetricSecurityKey(Encoding.UTF8
.GetBytes(_config.GetSection("AppSettings:Token").Value));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = DateTime.Now.AddDays(1),
SigningCredentials = creds
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
}
3.34 使用认证中间件
JwtBearerDefaults.AuthenticationScheme
在此处向 DI 注册:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII
.GetBytes(Configuration.GetSection("AppSettings:Token").Value)),
ValidateIssuer = false,
ValidateAudience = false
};
});
}
}
4.39 Angular服务介绍
用户的 token 在成功登录后存储到浏览器的本地存储中:
auth.service.ts
export class AuthService {
login(model: any) {
return this.http.post(this.baseUrl + ‘login’, model).pipe(
map((response: any) => {
const user = response;
if(user) { localStorage.setItem(‘token’, user.token);}}));}}
6.55 使用 Angular JWT 库解码 token
将解码 token 的属性添加到 authService.ts
13.134 使用 Action 过滤器
你可以:
通过 Action Filter 中的 Claim 验证许可证 key
通过ActionExecutingContext判断当前API路由
下面是一个从 Action Filter 中检索用户声明以及解析服务的示例:
public class LogUserActivity : IAsyncActionFilter
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
var resultContext = await next();
var userId = int.Parse(resultContext.HttpContext.User
.FindFirst(ClaimTypes.NameIdentifier).Value);
var repo = resultContext.HttpContext.RequestServices.GetService<IDatingRepository>();
var user = await repo.GetUser(userId, true);
user.LastActive = DateTime.Now;
await repo.SaveAll();
}
}
关于c# - Asp.net core 2.1 web api中的自定义授权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53643029/