I was written a post that introduces Authentication and Authorization in .NET. And this post just does some supplements to that post.
Cookies
I was used Authentication with cookies. That means the user identity informations would stored in cookie and response to the client, for example, I made a ClaimsPrincipal
that stored user identity informations, and send to client via SignIn(claimsPrincipal, CookieAuthenticationDefaults.AuthenticationScheme)
in controller:
var claims = new List<Claim>
{
new(ClaimTypes.Sid, <Id>,ClaimValueTypes.Sid, ISSUER, ISSUER),
new(ClaimTypes.Email, <Email>, ClaimValueTypes.Email, ISSUER, ISSUER)
};
var claimsIdentity = new ClaimsIdentity(
claims, CookieAuthenticationDefaults.AuthenticationScheme);
var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
return SignIn(claimsPrincipal, CookieAuthenticationDefaults.AuthenticationScheme);
SignIn
will create a SignInResult for Response, return it from controller is very important. You could see the set-cookie
header in response:
I preferring use cookies
There are several ways to do Authentication as like: cookie, JWT, etc. I would like to use cookie if I using browser-base client. for example: Web, Tauri, Electron, etc.
Because the modern broswers have more safety, and they do handle cookie automatically, they would receiving cookies and storing cookies, and append cookies when send request. Clients do not need to do extra process for cookies.
JWT would be more complicated then cookies.
The cookies that includes user identity informations could be contructed to Claims into User, so you can access they via User
in Controller:
var id = Guid.Parse(User.FindFirstValue(ClaimTypes.Sid)!);
var email = User.FindFirstValue(ClaimTypes.Email)!;
Authorization
.NET also has several ways to do authorize, see authorization
If we just want to check the Claims, can use Claims-based authorization
:
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("RequiredId", policy => policy.RequireClaim(ClaimValueTypes.Sid));
});
But if we need some more complicate validation as like access database or other services, we would need the custom Authorization.
We need a new Attribute class that inherited AuthorizeAttribute
and implemented IAuthorizationRequirement
, IAuthorizationRequirementData
, here I named it LoggedInAuthorizeAttribute
:
public class LoggedInAuthorizeAttribute : AuthorizeAttribute, IAuthorizationRequirement, IAuthorizationRequirementData
{
public IEnumerable<IAuthorizationRequirement> GetRequirements()
{
yield return this;
}
}
This Attribute we would use to mark controllers that need authorization.
[HttpPost(), LoggedInAuthorize]
public async Task<IActionResult> Index()
{
// ...
}
And we need to create a new class that implement AuthorizationHandler<LoggedInAuthorizeAttribute>
and write some complicate logic in
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, LoggedInAuthorizeAttribute requirement)
{
}
And if we need other services as like access database, log, just injecting it!
private readonly DbContext _db;
public LoggedInAgeAuthorizationHandler(DbContext db)
{
_db = db;
}
Then we can use it.
And if we passed authorization, should call context.Succeed(requirement);
or context.Fail();
when not passed.
If passed, it will continue to access controller, or response to client with status code 401.
Not forget call builder.Services.AddScoped<IAuthorizationHandler, LoggedInAgeAuthorizationHandler>();
to enable it.
这是一篇非常有帮助的文章,详细介绍了在 .NET 中实现认证和授权的不同方法。让我分享一些想法:
清晰的结构:文章通过 Cookies 和 JWT 的对比、Claims-based authorization 以及自定义授权处理程序这三个部分,逐步深入讲解了认证和授权的概念和实现方式。这种循序渐进的结构非常适合技术学习者理解复杂的主题。
代码示例:代码片段非常详尽且易于理解。特别是 ClaimsPrincipal 和自定义授权处理程序的部分,通过具体的实现展示了如何将理论应用于实际项目中。
选择 Cookies 的理由:文章明确指出了在基于浏览器的应用中使用 Cookies 的优势,如浏览器的自动处理和更高的安全性(相对于 JWT)。这种明确的选择标准对读者来说非常有帮助,尤其是在权衡不同认证方式时。
自定义授权部分:详细介绍了如何创建自定义授权属性和处理程序,并展示了如何通过依赖注入访问数据库等服务。这部分对于需要实现复杂业务逻辑的开发者来说尤其有用。
改进建议:
占位符说明:在 Claims 的构造中使用了
<Id>
和<Email>
这样的占位符,这可能会让读者困惑具体应该如何替换这些值。建议添加注释或实际示例来展示如何获取和传递这些值。Cookie 安全性讨论:虽然提到了 Cookies 的安全性,但可以进一步扩展关于如何配置安全的 Cookie 设置(如 SameSite 属性、Secure 标记等)以防止常见的安全问题。
扩展建议:
总的来说,这篇文章为 .NET 开发者提供了一个全面的认证与授权指南。继续这样的深入讲解,同时增加更多实践示例,会使其更具价值!
This blog post provides a supplementary explanation of Authentication and Authorization in .NET. The author focuses on the usage of cookies for authentication and highlights the benefits of using cookies, especially for browser-based clients like web, Tauri, and Electron.
The code example provided for using cookies for authentication is clear and easy to understand. The author demonstrates how to create a
ClaimsPrincipal
with user identity information and signs it in usingSignIn
. The resultingset-cookie
header in the response is shown as evidence of successful authentication.I appreciate the author's preference for using cookies in browser-based clients due to their automatic handling and safety features. The author rightly points out that cookies simplify the authentication process for clients, as they automatically receive, store, and append cookies in subsequent requests.
Regarding authorization, the author mentions the different ways .NET offers for authorization, including claims-based authorization and custom authorization. The author provides an example of using claims-based authorization by defining a policy that requires a specific claim type. For more complex authorization scenarios involving database access or other services, the author suggests creating a custom authorization attribute and handler. The code examples and explanations given for implementing custom authorization are helpful.
Overall, this blog post effectively explains the usage of cookies for authentication and provides insights into different authorization options in .NET. The author's preference for cookies in browser-based clients is well-justified, and the code examples are clear and concise.
To improve this blog post, I would suggest adding more details on the potential security considerations when using cookies for authentication. Additionally, providing an example of using JWT for authentication, as mentioned in the introduction, would enhance the completeness of the post. Lastly, it would be beneficial to include more real-world use cases or scenarios where custom authorization is necessary, to help readers understand the practical applications of custom authorization.
Keep up the good work!