https://www.cnblogs.com/KimmyLee/p/6430474.html

https://www.cnblogs.com/rocketRobin/p/9077523.html

http://bitoftech.net/2015/03/31/asp-net-web-api-claims-authorization-with-asp-net-identity-2-1/

ASP.NET Web API Claims Authorization with ASP.NET Identity 2.1

In the previous post we have implemented a finer grained way to control authorization based on the Roles assigned for the authenticated user, this was done by assigning users to a predefined Roles in our system and then attributing the protected controllers or actions by the [Authorize(Roles = “Role(s) Name”)]attribute.

Using Roles Based Authorization for controlling user access will be efficient in scenarios where your Roles do not change too much and the users permissions do not change frequently.

In some applications controlling user access on system resources is more complicated, and having users assigned to certain Roles is not enough for managing user access efficiently, you need more dynamic way to to control access based on certain information related to the authenticated user, this will lead us to control user access using Claims, or in another word using Claims Based Authorization.

But before we dig into the implementation of Claims Based Authorization we need to understand what Claims are!

Note: It is not mandatory to use Claims for controlling user access, if you are happy with Roles Based Authorization and you have limited number of Roles then you can stick to this.

What is a Claim?

Claim is a statement about the user makes about itself, it can be user name, first name, last name, gender, phone, the roles user assigned to, etc… Yes the Roles we have been looking at are transformed to Claims at the end, and as we saw in the previous post; in ASP.NET Identity those Roles have their own manager (ApplicationRoleManager) and set of APIs to manage them, yet you can consider them as a Claim of type Role.

As we saw before, any authenticated user will receive a JSON Web Token (JWT) which contains a set of claims inside it, what we’ll do now is to create a helper end point which returns the claims encoded in the JWT for an authenticated user.

To do this we will create a new controller named “ClaimsController” which will contain a single method responsible to unpack the claims in the JWT and return them, to do this add new controller named “ClaimsController” under folder Controllers and paste the code below:

[RoutePrefix("api/claims")]
public class ClaimsController : BaseApiController
{
[Authorize]
[Route("")]
public IHttpActionResult GetClaims()
{
var identity = User.Identity as ClaimsIdentity; var claims = from c in identity.Claims
select new
{
subject = c.Subject.Name,
type = c.Type,
value = c.Value
}; return Ok(claims);
} }

The code we have implemented above is straight forward, we are getting the Identity of the authenticated user by calling “User.Identity” which returns “ClaimsIdentity” object, then we are iterating over the IEnumerable Claims property and return three properties which they are (Subject, Type, and Value).
To execute this endpoint we need to issue HTTP GET request to the end point “http://localhost/api/claims” and do not forget to pass a valid JWT in the Authorization header, the response for this end point will contain the below JSON object:

[

  {
    "subject": "Hamza",
    "type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
    "value": "cd93945e-fe2c-49c1-b2bb-138a2dd52928"
  },
  {
    "subject": "Hamza",
    "type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
    "value": "Hamza"
  },
  {
    "subject": "Hamza",
    "type": "http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider",
    "value": "ASP.NET Identity"
  },
  {
    "subject": "Hamza",
    "type": "AspNet.Identity.SecurityStamp",
    "value": "a77594e2-ffa0-41bd-a048-7398c01c8948"
  },
  {
    "subject": "Hamza",
    "type": "iss",
    "value": "http://localhost:59822"
  },
  {
    "subject": "Hamza",
    "type": "aud",
    "value": "414e1927a3884f68abc79f7283837fd1"
  },
  {
    "subject": "Hamza",
    "type": "exp",
    "value": "1427744352"
  },
  {
    "subject": "Hamza",
    "type": "nbf",
    "value": "1427657952"
  }
]

As you noticed from the response above, all the claims contain three properties, and those properties represents the below:

  • Subject: Represents the identity which those claims belongs to, usually the value for the subject will contain the unique identifier for the user in the system (Username or Email).
  • Type: Represents the type of the information contained in the claim.
  • Value: Represents the claim value (information) about this claim.

Now to have better understanding of what type of those claims mean let’s take a look the table below:

SUBJECT TYPE VALUE NOTES
Hamza nameidentifier cd93945e-fe2c-49c1-b2bb-138a2dd52928 Unique User Id generated from Identity System
Hamza name Hamza Unique Username
Hamza identityprovider ASP.NET Identity How user has been authenticated using ASP.NET Identity
Hamza SecurityStamp a77594e2-ffa0-41bd-a048-7398c01c8948 Unique Id which stays the same until any security related attribute change, i.e. change user password
Hamza iss http://localhost:59822 Issuer of the Access Token (Authz Server)
Hamza aud 414e1927a3884f68abc79f7283837fd1 For which system this token is generated
Hamza exp 1427744352 Expiry time for this access token (Epoch)
Hamza nbf 1427657952 When this token is issued (Epoch)

After we have briefly described what claims are, we want to see how we can use them to manage user assess, in this post I will demonstrate three ways of using the claims as the below:

  1. Assigning claims to the user on the fly based on user information.
  2. Creating custom Claims Authorization attribute.
  3. Managing user claims by using the “ApplicationUserManager” APIs.

Method 1: Assigning claims to the user on the fly

Method 2: Creating custom Claims Authorization attribute

Method 3: Managing user claims by using the “ApplicationUserManager” APIs

The last method we want to explore here is to use the “ApplicationUserManager” claims related API to manage user claims and store them in ASP.NET Identity related tables “AspNetUserClaims”.

In the previous two methods we’ve created claims for the user on the fly, but in method 3 we will see how we can add/remove claims for a certain user.

The “ApplicationUserManager” class comes with a set of predefined APIs which makes dealing and managing claims simple, the APIs that we’ll use in this post are listed in the table below:

METHOD NAME USAGE
AddClaimAsync(id, claim) Create a new claim for specified user id
RemoveClaimAsync(id, claim) Remove claim from specified user if claim type and value match
GetClaimsAsync(id) Return IEnumerable of claims based on specified user id

To use those APIs let’s add 2 new methods to the “AccountsController”, the first method “AssignClaimsToUser” will be responsible to add new claims for specified user, and the second method “RemoveClaimsFromUser” will remove claims from a specified user as the code below:

[Authorize(Roles = "Admin")]
[Route("user/{id:guid}/assignclaims")]
[HttpPut]
public async Task<IHttpActionResult> AssignClaimsToUser([FromUri] string id, [FromBody] List<ClaimBindingModel> claimsToAssign) { if (!ModelState.IsValid)
{
return BadRequest(ModelState);
} var appUser = await this.AppUserManager.FindByIdAsync(id); if (appUser == null)
{
return NotFound();
} foreach (ClaimBindingModel claimModel in claimsToAssign)
{
if (appUser.Claims.Any(c => c.ClaimType == claimModel.Type)) { await this.AppUserManager.RemoveClaimAsync(id, ExtendedClaimsProvider.CreateClaim(claimModel.Type, claimModel.Value));
} await this.AppUserManager.AddClaimAsync(id, ExtendedClaimsProvider.CreateClaim(claimModel.Type, claimModel.Value));
} return Ok();
} [Authorize(Roles = "Admin")]
[Route("user/{id:guid}/removeclaims")]
[HttpPut]
public async Task<IHttpActionResult> RemoveClaimsFromUser([FromUri] string id, [FromBody] List<ClaimBindingModel> claimsToRemove)
{ if (!ModelState.IsValid)
{
return BadRequest(ModelState);
} var appUser = await this.AppUserManager.FindByIdAsync(id); if (appUser == null)
{
return NotFound();
} foreach (ClaimBindingModel claimModel in claimsToRemove)
{
if (appUser.Claims.Any(c => c.ClaimType == claimModel.Type))
{
await this.AppUserManager.RemoveClaimAsync(id, ExtendedClaimsProvider.CreateClaim(claimModel.Type, claimModel.Value));
}
} return Ok();
}

The implementation for both methods is very identical, as you noticed we are only allowing users in “Admin” role to access those endpoints, then we are specifying the UserId and a list of the claims that will be add or removed for this user.

Then we are making sure that user specified exists in our system before trying to do any operation on the user.

In case we are adding a new claim for the user, we will check if the user has the same claim type before trying to add it, add if it exists before we’ll remove this claim and add it again with the new claim value.

The same applies when we try to remove a claim from the user, notice that methods “AddClaimAsync” and “RemoveClaimAsync” will save the claims permanently in our SQL data-store in table “AspNetUserClaims”.

Do not forget to add the “ClaimBindingModel” under folder “Models” which acts as our POCO class when we are sending the claims from our front-end application, the class will contain the code below:

public class ClaimBindingModel
{
[Required]
[Display(Name = "Claim Type")]
public string Type { get; set; } [Required]
[Display(Name = "Claim Value")]
public string Value { get; set; }
}

There is no extra steps needed in order to pull those claims from the SQL data-store when establishing the user identity, thanks for the method “CreateIdentityAsync” which is responsible to pull all the claims for the user. We have already implemented this and it can be checked by visiting the highlighted LOC.

To test those methods all you need to do is to issue HTTP PUT request to the URI: “http://localhost:59822/api/accounts/user/{UserId}/assignclaims” and “http://localhost:59822/api/accounts/user/{UserId}/removeclaims” as the request images below:

That’s it for now folks about implementing Authorization using Claims.

ASP.NET Web API Claims Authorization with ASP.NET Identity 2.1 Part 5 (by TAISEER)的更多相关文章

  1. 【ASP.NET Web API教程】1 ASP.NET Web API入门

    原文 [ASP.NET Web API教程]1 ASP.NET Web API入门 Getting Started with ASP.NET Web API第1章 ASP.NET Web API入门 ...

  2. Announcing the Release of ASP.NET MVC 5.1, ASP.NET Web API 2.1 and ASP.NET Web Pages 3.1 for VS2012

    The NuGet packages for ASP.NET MVC 5.1, ASP.NET Web API 2.1 and ASP.NET Web Pages 3.1 are now live o ...

  3. Implement JSON Web Tokens Authentication in ASP.NET Web API and Identity 2.1 Part 3 (by TAISEER)

    http://bitoftech.net/2015/02/16/implement-oauth-json-web-tokens-authentication-in-asp-net-web-api-an ...

  4. 杂项:ASP.NET Web API

    ylbtech-杂项:ASP.NET Web API ASP.NET Web API 是一种框架,用于轻松构建可以访问多种客户端(包括浏览器和移动设备)的 HTTP 服务. ASP.NET Web A ...

  5. ASP.NET Web API 控制器执行过程(一)

    ASP.NET Web API 控制器执行过程(一) 前言 前面两篇讲解了控制器的创建过程,只是从框架源码的角度去简单的了解,在控制器创建过后所执行的过程也是尤为重要的,本篇就来简单的说明一下控制器在 ...

  6. ASP.NET Web API WebHost宿主环境中管道、路由

    ASP.NET Web API WebHost宿主环境中管道.路由 前言 上篇中说到ASP.NET Web API框架在SelfHost环境中管道.路由的一个形态,本篇就来说明一下在WebHost环境 ...

  7. ASP.NET Web API Selfhost宿主环境中管道、路由

    ASP.NET Web API Selfhost宿主环境中管道.路由 前言 前面的几个篇幅对Web API中的路由和管道进行了简单的介绍并没有详细的去说明一些什么,然而ASP.NET Web API这 ...

  8. ASP.NET Web API 管道模型

    ASP.NET Web API 管道模型 前言 ASP.NET Web API是一个独立的框架,也有着自己的一套消息处理管道,不管是在WebHost宿主环境还是在SelfHost宿主环境请求和响应都是 ...

  9. ASP.NET Web API 路由对象介绍

    ASP.NET Web API 路由对象介绍 前言 在ASP.NET.ASP.NET MVC和ASP.NET Web API这些框架中都会发现有路由的身影,它们的原理都差不多,只不过在不同的环境下作了 ...

随机推荐

  1. java通过ping 判断网络是否正常

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.i ...

  2. JavaScript学习(5)-Image对象和动态HTML

    JavaScript学习5 1.image 对象 对象引用 document.images[n] document.images["imageName"] document.ima ...

  3. odex反编译dex异常 Cannot locate boot class path file /system/framework/core.odex

      为了将ROM中system/app下的CertInstaller.odex反编译为CertInstaller.dex,输入命令: "java -jar baksmali.jar -x C ...

  4. Photoshop打开时报错“不能打开暂存盘文件。。。”

    解决方法: 1.找到应用程序(Photoshop.exe文件) 2.右键 -> 属性 -> 兼容性 -> 更改所有用户的设置 -> 勾选上“以管理员身份运行此程序”.

  5. Linux命令:nl

    全称:number lines of files 用途:显示的时候添加行号. 格式:nl [OPTION]... [FILE]... 类型:nl is /usr/bin/nl 说明: 该命令主要就是针 ...

  6. SpringBoot-基于Maven工程使用SpringBoot

    Spring Boot SpringBoot是一个社区反馈推动的项目.SpringBoot可以说是至少五年来Spring乃至整个Java社区最有影响力的项目之一.SpringBoot主要包括以下特性: ...

  7. Mybatis的MapperRegistry错误

    1,如果mabtis的配置文件里mapper用的不是包扫描,而是: <mapper resource="com/vmpjin/mapper/OrdersMapper.xml" ...

  8. ECMAScript 6 学习资料

    ECMAScript 6入门 http://es6.ruanyifeng.com/ 30分钟掌握ES6/ES2015核心内容(上) 30分钟掌握ES6/ES2015核心内容(下)

  9. 控制台应用程序中添加对MFC的支持

    在windows控制台应用程序中,肯能会想使用一些MFC中的类,如CStringArray等,通过下面两步简单的设置可以添加对MFC的支持: 1.右击工程名 -> References 选择 A ...

  10. 浅析selenium的PageFactory模式 PageFactory初始化pageobject

    1.首先介绍FindBy类: For example, these two annotations point to the same element: @FindBy(id = "foob ...