gpt4 book ai didi

c# - Web API中基于 token 的实现可保护端点

转载 作者:行者123 更新时间:2023-11-30 21:37:34 25 4
gpt4 key购买 nike

我有一个带有Web服务的Web应用程序,客户端将使用我的Web应用程序注册其应用程序。

现在,客户端将拥有SPA或移动应用程序类型的应用程序,并且他们将从其应用程序中使用我的Web服务。

因此,我将实现基于令牌的机制来保护对端点的访问。

1)但是在这里我很困惑,我应该使用任何框架来生成访问令牌,还是可以使用任何库来生成将响应地发送的任何随机字符串,例如:

TokenId = Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Replace("+", "_")


因此,在注册应用程序时,如果客户端已为其应用程序启用身份验证,则将验证用户,然后我将返回访问令牌,并使用该用户ID将访问令牌保存在我的数据库中。

所以我的数据库表如下所示,用于存储经过验证的accesstoken:

Id(autogenerated)   accesstoken    userid   clientid    createdat    expiresat


因此,在对用户进行身份验证之后,现在,如果用户要访问任何受保护的资源,则用户需要在后续的标头调用中传递此访问令牌。

因此,我将执行的操作是从标头获取访问令牌,然后针对该数据库验证该访问令牌,然后允许对我受保护的资源的访问,否则,明智的用户将获得授权。

我已经看到了很多与此相关的东西,所以基本上是oauth2,我想实现它。

我已经看到 Openid connect(该项目甚至不编译),它位于oauth2之上,用于身份验证,而oauth2将用于授权。

但是在这里,因为我将访问令牌存储在数据库中,所以我对此有疑问:

2)现在我需要使用openconnectid(但该项目甚至不编译)来验证访问令牌还是由于我将访问令牌存储在数据库中而不需要openconnectid?

3)我想实现asp.net身份,但随后我将收到动态数据库连接字符串,并且正如我所见,asp.net身份主要与实体框架一起使用,我找不到可以使用ado.net验证用户名的任何来源和密码使用SQL查询。我知道我可以做这样的事情:

制作一个自定义用户类,该类实现 here中所述的IUser
定义实现的自定义用户存储

public class UserStoreService 
: IUserStore<CustomUser>, IUserPasswordStore<CustomUser>


但是我不会得到此信息,因为我没有固定的连接字符串。连接字符串再次通过客户端注册存储在数据库中。

4)我们为用户提供了一个固定的端点,客户端可以通过该端点创建管理员,因此我将使用RSA算法进行密码哈希处理,然后将其存储在数据库中。因此,现在我需要使用asp.net身份吗?

5)我已经看到许多以下基于令牌的实现的链接,但是我没有得到它们在哪个部分验证accesstoken的位置,但是当我将accesstoken存储在数据库中时,是否需要使用以下任何实现?

http://bitoftech.net/2014/10/27/json-web-token-asp-net-web-api-2-jwt-owin-authorization-server/

http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/

6)此外,如果对于任何客户端,如果客户端不希望对其各自的应用程序进行身份验证,那么我要做的是,我将没有该用户名密码验证,但是我只会生成访问令牌,然后发送响应,因此在以后的每个后续操作中请求将访问令牌传递给访问受保护的资源。您认为这样做有意义吗?

我从未见过将访问令牌存储在数据库中以及将访问令牌存储在数据库中的问题的任何示例,因为我每次都必须调用数据库来验证每个端点的访问令牌。

更新:

我的Web服务引擎的用例为:

1)支持多个客户端应用程序。

2)以令牌管理的形式管理每个客户端应用程序的用户会话。因此,在这里,由于本文的大部分内容都将访问令牌存储在身份中,并且该身份在[Authorize]属性中得到了验证,在该属性中,访问令牌也得到了验证,并允许该用户基于该用户访问受保护的资源。这是我到目前为止的理解。

因此,如果我也将用户身份和用户上下文存储在支持多个客户端应用程序的身份中是一个好主意吗?

最佳答案

不,您不需要将access_token存储在数据库中。您可以解密JWT并读取信息,因为您是使用密钥对它进行加密的人。 (默认情况下,这是机器密钥。)

身份对Oauth缺乏自我支持。您只需要正确配置它。您可以在Startup.Auth.cs中设置OAuthAuthorizationServerOptions的配置。示例代码如下。我已尝试在代码的注释中回答您的大多数问题。

public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }

public static string PublicClientId { get; private set; }

public void ConfigureOAuth(IAppBuilder app)
{
// Configure the application for OAuth based flow
PublicClientId = "theDragonIsAlive";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new YourOwnApplicationOAuthProvider(PublicClientId),
//AuthorizeEndpointPath = new PathString("/Access/Account"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(7)
//AllowInsecureHttp = true
};

// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);

}

public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{
private readonly string _publicClientId;

public ApplicationOAuthProvider(string publicClientId)
{
if (publicClientId == null)
{
throw new ArgumentNullException("publicClientId");
}

_publicClientId = publicClientId;
}

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
// This where you are validating the username and password credentials.
ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);

if (user == null)
{
context.SetError("Dragon Fire:", "The user name or password is incorrect. You shall be burnt.");
return;
}

ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
OAuthDefaults.AuthenticationType);

AuthenticationProperties properties = CreateProperties(user.UserName);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(oAuthIdentity);
}

public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
{
context.AdditionalResponseParameters.Add(property.Key, property.Value);
}

return Task.FromResult<object>(null);
}

// This method is where you will create the client access token.
// First you get the client, you can place values from the client record into the tokens claim collection.
// You then create a new ClaimsIdentity.
// You add some claims, in the example client name is added.
// Create an AuthenticationTicket using your claims identity.
// Validate the ticket (you do need to do this or the client will be considered unauthenticated)
//public override Task GrantClientCredentials(OAuthGrantClientCredentialsContext context)
//{
// var client = clientService.GetClient(context.ClientId);
// var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
// oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name, client.ClientName));
// var ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties());
// context.Validated(ticket);
// return base.GrantClientCredentials(context);
//}

// This method has to be implmented when you are maintaining a list of clients which you will allow.
// This method is for validating the input, you can used this method to verify the client id and secret are valid.
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
//string clientId;
//string clientSecret;
//context.TryGetFormCredentials(out clientId, out clientSecret);

//if (clientId == "1234" && clientSecret == "12345")
//{
// context.Validated(clientId);
//}

//return base.ValidateClientAuthentication(context);

// Resource owner password credentials does not provide a client ID.
if (context.ClientId == null)
{
context.Validated();
}

return Task.FromResult<object>(null);
}

public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
{
if (context.ClientId == _publicClientId)
{
Uri expectedRootUri = new Uri(context.Request.Uri, "/");

if (expectedRootUri.AbsoluteUri == context.RedirectUri)
{
context.Validated();
}
}

return Task.FromResult<object>(null);
}

public static AuthenticationProperties CreateProperties(string userName)
{
IDictionary<string, string> data = new Dictionary<string, string>
{
{ "userName", userName }
};
return new AuthenticationProperties(data);
}
}


上面的示例代码没有单独的客户端分类。它将所有用户视为单一类型的客户端。但是我在注释中给出了一些示例代码,这些代码将指导您开始正确的方向。

免责声明:我还不是专家,我的设置也有所不同。我在Owin上有一个现有的MVC应用程序,必须在其之上构建一个webapi。这是我的原型代码,它完成了工作。您将不得不为您的生产代码进行改进。玩得开心,祝你好运。

关于c# - Web API中基于 token 的实现可保护端点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47096113/

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