Oauth2、OIDC、权限控制

原文链接:http://www.cnblogs.com/linianhui/p/permission-based-access-control.html

OAuth2和OIDC(OpenId Connect),其作用是授权和认证。那么当我们得到OAuth2的Access Token或者OIDC的Id Token之后,我们的资源服务如何来验证这些token是否有权限来执行对资源的某一项操作呢?

比如我有一个API,/books,它具有如下5个操作:

  1. POST /books        添加一本书
  2. GET /books/{id}        获取一本书
  3. PUT /books/{id}更新一本书
  4. DELETE /books/{id}删除一本书
  5. GET /books  获取书的列表

其伪代码如下:

[Route("books")]

public class BooksController : Controller

{

    [HttpGet("")]

    public Book[] Get() { return null; }

    [HttpGet("{bookId}")]

    public Book Get(int bookId) { return null; }

    [HttpPost("")]

    public Book Post(Book book) { return null; }

    [HttpPut("{bookId}")]

    public Book Put(int bookId, Book book) { return null; }

    [HttpDelete("{bookId}")]

    public Book Delete(int bookId) { return null; }

}

那么我们先看看基于OAuth2的Access Token,OIDC的Id Token和传统的基于角色的权限控制是如何处理控制这些资源的操作。

1 OAuth2的Access Token之Scope

我们都知道OAuth2的最终产物是提供给我们一个Access Token,而这个Access Token中包含了一个Scope的字段,这个字段代表的是授权服务器或者资源拥有者授予第三方客户端允许操作资源服务器的哪些资源的范围

这里有一点需要注意的是,

这个授权过程可以有资源拥有着的参与(Authorization Code,Implicit,Resource Owner Password Credentials Grant),

也可以没有他的参与(Client Credentials Grant)。

那么基于上述的books的资源,我们可以定义一个 book_manager 的Scope,来控制对books的五个操作的权限控制。

那么Books的基于Scope的权限控制看起来就像是这样的:

[Route("books")]

public class BooksController : Controller

{

    [HttpGet("")]

    [Scope("book_manager")]

    public Book[] Get() { return null; }

    [HttpGet("{bookId}")]

    [Scope("book_manager")]

    public Book Get(int bookId) { return null; }

    [HttpPost("")]

    [Scope("book_manager")]

    public Book Post(Book book) { return null; }

    [HttpPut("{bookId}")]

    [Scope("book_manager")]

    public Book Put(int bookId, Book book) { return null; }

    [HttpDelete("{bookId}")]

    [Scope("book_manager")]

    public Book Delete(int bookId) { return null; }

}

注意看字体加粗的部分,为每一个操作都添加了一个Scope的描述。如果Access Token拥有book_manager这个Scope(不管他是OAuth2的哪一个授权方式颁发的,我们的最终代码部分只认Scope),那么对这些API的调用就是被允许的,否则视为无权操作。

2 OIDC的Id Token之sub

关于Id Token的用途以及其包含哪些信息请参考Id Token。Id Token和Access Token的不同之处在于它一定是包含某一个用户的标识 sub ,但是没有Scope,这是因为Id Token的用途是认证当前用户是谁,所以用户是必须存在的;由于仅仅是认证,则不会包含被认证用户可以做哪些操作之类的授权相关的事情。那么针对Id Token,我们的API应该如何进行权限管控呢?通常的做法是使用传统的基于角色的权限控制(Role Based Access Control)。其实现细节就不解释了,它的模型大致是:一个实体(用户或者组织)拥有一组角色,每一个角色代表着一组权限集合。感觉是不是和Scope很像呢,其实差不多。我们定义一个这样的角色 图书管理员 吧。这里是故意和Scope的命名区分开的,因为其来源不同,那么我们最终实现的时候也会是独立开来的。

 [Route("books")]

  public class BooksController : Controller

  {

      [HttpGet("")]

      [Scope("book_manager")]

     [Role("图书管理员")]

     public Book[] Get() { return null; }

  

      [HttpGet("{bookId}")]

     [Scope("book_manager")]

     [Role("图书管理员")]

     public Book Get(int bookId) { return null; }

     [HttpPost("")]

     [Scope("book_manager")]

     [Role("图书管理员")]

     public Book Post(Book book) { return null; }

     [HttpPut("{bookId}")]

     [Scope("book_manager")]

     [Role("图书管理员")]

     public Book Put(int bookId, Book book) { return null; }

     [HttpDelete("{bookId}")]

     [Scope("book_manager")]

     [Role("图书管理员")]

     public Book Delete(int bookId) { return null; }

 }

如果 sub 代表的用户自身拥有或者其所属的组织机构拥有(不管其是怎么组织管理的吧,最终我们可以知道这个用户是否具有某一个角色) 图书管理员 这个角色。则允许其访问books的这些操作。

猜你喜欢

转载自huangqiqing123.iteye.com/blog/2410818
今日推荐