gpt4 book ai didi

c# - 使用本地帐户使用安全的 ASP Net 5 web api

转载 作者:太空狗 更新时间:2023-10-29 20:41:25 24 4
gpt4 key购买 nike

我需要使用本地帐户从 Web 客户端使用 ASP.NET 5 安全 Web API。过去有一个处理程序发布不记名 token 以支持 OAuth,现在不记名 token 发布责任已从身份中删除。有些人建议使用 identityServer3,它需要客户端注册,这与 identity2 方法不同。在 ASP.NET 5 Web API 中实现授权的最简单方法是什么?在使用资源所有者密码流时,如何避免传递客户端 ID 和客户端密码以获取访问 token ?如何调用api避免通过作用域?

最佳答案

我从 this 构建了一个简单的不记名 token 发行者,但使用身份密码哈希器。您可以在下面查看完整代码:

public class TokenController : Controller
{
private readonly IBearerTokenGenerator generator;
private readonly IClientsManager clientsManager;
private readonly IOptions<TokenAuthOptions> options;

public TokenController(IBearerTokenGenerator generator,
IClientsManager clientsManager,
IOptions<TokenAuthOptions> options)
{
this.generator = generator;
this.clientsManager = clientsManager;
this.options = options;
}

[HttpPost, AllowAnonymous]
public IActionResult Post(AuthenticationViewModel req)
{
return clientsManager
.Find(req.client_id, req.client_secret)
.Map(c => c.Client)
.Map(c => (IActionResult)new ObjectResult(new {
access_token = generator.Generate(c),
expires_in = options.Value.ExpirationDelay.TotalSeconds,
token_type = "Bearer"
}))
.ValueOrDefault(HttpUnauthorized);
}
}

public class BearerTokenGenerator : IBearerTokenGenerator
{
private readonly IOptions<TokenAuthOptions> tokenOptions;

public BearerTokenGenerator(IOptions<TokenAuthOptions> tokenOptions)
{
this.tokenOptions = tokenOptions;
}

public string Generate(Client client)
{
var expires = Clock.UtcNow.Add(tokenOptions.Value.ExpirationDelay);
var handler = new JwtSecurityTokenHandler();

var identity = new ClaimsIdentity(new GenericIdentity(client.Identifier, "TokenAuth"), new Claim[] {
new Claim("client_id", client.Identifier)
});

var securityToken = handler.CreateToken(
issuer: tokenOptions.Value.Issuer,
audience: tokenOptions.Value.Audience,
signingCredentials: tokenOptions.Value.SigningCredentials,
subject: identity,
expires: expires);

return handler.WriteToken(securityToken);
}
}

public class ClientsManager : IClientsManager
{
private readonly MembershipDataContext db;
private readonly ISecretHasher hasher;

public ClientsManager(MembershipDataContext db,
ISecretHasher hasher)
{
this.db = db;
this.hasher = hasher;
}

public void Create(string name, string identifier, string secret, Company company)
{
var client = new Client(name, identifier, company);
db.Clients.Add(client);

var hash = hasher.HashSecret(secret);
var apiClient = new ApiClient(client, hash);

db.ApiClients.Add(apiClient);
}

public Option<ApiClient> Find(string identifier, string secret)
{
return FindByIdentifier(identifier)
.Where(c => hasher.Verify(c.SecretHash, secret));
}

public void ChangeSecret(string identifier, string secret)
{
var client = FindByIdentifier(identifier).ValueOrDefault(() => {
throw new ArgumentException($"could not find any client with identifier { identifier }");
});

var hash = hasher.HashSecret(secret);
client.ChangeSecret(hash);
}

public string GenerateRandomSecret()
{
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var random = new Random();
var generated = new string(Enumerable.Repeat(chars, 12).Select(s => s[random.Next(s.Length)]).ToArray());
return Convert.ToBase64String(Encoding.UTF8.GetBytes(generated));
}

private Option<ApiClient> FindByIdentifier(string identifier)
{
return db.ApiClients
.Include(c => c.Client)
.SingleOrDefault(c => c.Client.Identifier == identifier)
.ToOptionByRef();
}
}

public class SecretHasher : ISecretHasher
{
private static Company fakeCompany = new Company("fake", "fake");
private static Client fakeClient = new Client("fake", "fake", fakeCompany);

private readonly IPasswordHasher<Client> hasher;

public SecretHasher(IPasswordHasher<Client> hasher)
{
this.hasher = hasher;
}

public string HashSecret(string secret)
{
return hasher.HashPassword(fakeClient, secret);
}

public bool Verify(string hashed, string secret)
{
return hasher.VerifyHashedPassword(fakeClient, hashed, secret) == PasswordVerificationResult.Success;
}
}

现在在 Startup.cs 中

            services.Configure<TokenAuthOptions>(options =>
{
options.Audience = "API";
options.Issuer = "Web-App";
options.SigningCredentials = new SigningCredentials(GetSigninKey(), SecurityAlgorithms.RsaSha256Signature);
options.ExpirationDelay = TimeSpan.FromDays(365);
});

services.AddAuthorization(auth =>
{
auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme‌​)
.RequireAuthenticatedUser()
.Build());
}

app.UseJwtBearerAuthentication(options =>
{
options.TokenValidationParameters.IssuerSigningKey = GetSigninKey();
options.TokenValidationParameters.ValidAudience = "API";
options.TokenValidationParameters.ValidIssuer = "Web-App";
options.TokenValidationParameters.ValidateSignature = true;
options.TokenValidationParameters.ValidateLifetime = true;
options.TokenValidationParameters.ClockSkew = TimeSpan.FromMinutes(0);
});

关于c# - 使用本地帐户使用安全的 ASP Net 5 web api,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34323094/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com