ASP.NET 基于查询字符串的核心授权
ASP.NET Core Authorization based on query string
我的 Web API 中有一个端点,如下所示:
api/customers?salesRepId=123
现在,如果我不在查询字符串中提供 salesRepId,我希望能够吸引所有客户。如果提供了 salesRepId,我只想拉取销售代表的客户。
只有管理员可以查看所有客户,这意味着当我以 salesRepId 123 登录并在没有查询字符串的情况下调用 api/customers 时,API 应该以 401(未授权)响应) 错误。
如何在 ASP.NET Core 2.0 Web API 中执行此操作?
另一种选择是暴露 2 个端点,我希望避免这种情况。
我假设 api/customers
的控制器看起来类似于以下内容(暂时忽略 return 类型):
[HttpGet("customers/{salesRepId}")]
public JsonResult Customers(int salesRepId)
而且我还假设您正在以某种方式单独处理授权(可能使用属性或某些中间件)。
如果是这样,我会将 salesRepId
参数更改为可为 null 的 int (here is a little about Nullable types, if you've not used them before),方法签名如下:
[HttpGet("customers/{salesRepId}")]
public JsonResult Customers(int? salesRepId)
然后我会检查 salesRepId
是否有一个值(即它作为 QueryString 的一部分提供),方法是:
[HttpGet("customers/{salesRepId}")]
public JsonResult Customers(int? salesRepId)
{
// userIsNotAuthorised is the name I'm giving to whatever
// whatever check you are making that the user is authorised
if (!salesRepId.HasValue && userIsNotAuthorised)
{
// return 401
}
// user is either authorised or has supplied a salesRepId or both
}
您还可以更改路由属性以匹配如下内容:
[HttpGet("customers/{salesRepId:int?}")]
public JsonResult Customers(int salesRepId = -1)
请注意,在本例中我必须提供默认选项。这将改变我们需要如何更改方法主体中的检查以匹配如下内容:
[HttpGet("customers/{salesRepId:int?}")]
public JsonResult Customers(int salesRepId = -1)
{
// userIsNotAuthorised is the name I'm giving to whatever
// whatever check you are making that the user is authorised
if (salesRepId == -1 && userIsNotAuthorised)
{
// return 401
}
// user is either authorised or has supplied a salesRepId or both
}
我个人更喜欢尽可能使用 Nullable 类型。这是因为在第二个示例中,我们依赖于 -1
(我们将其用作 magic number,这是一种反模式)。
您不需要 salesRepId
除了过滤。
当代表登录时,对 api/customers
的调用应该 return 管理员的所有客户和代表的所有客户。
调用 api/customers?salesRepId=123
应用相同的验证(可以通过 policy based authentcation 检查声明或范围),但过滤结果(属于一个代表的所有客户。
当管理员致电 api/customers?salesRepId=123
时,他收到的结果与销售代表致电 api/customers
或 api/customers?salesRepId=123
时收到的结果相同,但当销售代表致电 api/customers?salesRepId=456
时,他 returns 一个空结果(因为他的结果被 456 过滤结果为空)。
或者换句话说:如果用户是某种管理用户,控制器会将登录用户的 id 设置为销售代表过滤器。
这样您就不必以不同方式处理它,API 对每个用户的行为都相同。
不要忘记,RESTful 应用程序中的查询可以通过应用过滤来减少数据量。
或者,有两个路由操作的路由。 api/customers
具有我上面描述的行为和 api/salesrepresentative/123/customers
或 api/my/customers
(具体暗示它的范围缩小到登录用户)。这清楚地表明它是两种不同类型的资源。
第一个是所有客户的集合,而第二个是给定代表的所有客户。
我的 Web API 中有一个端点,如下所示:
api/customers?salesRepId=123
现在,如果我不在查询字符串中提供 salesRepId,我希望能够吸引所有客户。如果提供了 salesRepId,我只想拉取销售代表的客户。
只有管理员可以查看所有客户,这意味着当我以 salesRepId 123 登录并在没有查询字符串的情况下调用 api/customers 时,API 应该以 401(未授权)响应) 错误。
如何在 ASP.NET Core 2.0 Web API 中执行此操作?
另一种选择是暴露 2 个端点,我希望避免这种情况。
我假设 api/customers
的控制器看起来类似于以下内容(暂时忽略 return 类型):
[HttpGet("customers/{salesRepId}")]
public JsonResult Customers(int salesRepId)
而且我还假设您正在以某种方式单独处理授权(可能使用属性或某些中间件)。
如果是这样,我会将 salesRepId
参数更改为可为 null 的 int (here is a little about Nullable types, if you've not used them before),方法签名如下:
[HttpGet("customers/{salesRepId}")]
public JsonResult Customers(int? salesRepId)
然后我会检查 salesRepId
是否有一个值(即它作为 QueryString 的一部分提供),方法是:
[HttpGet("customers/{salesRepId}")]
public JsonResult Customers(int? salesRepId)
{
// userIsNotAuthorised is the name I'm giving to whatever
// whatever check you are making that the user is authorised
if (!salesRepId.HasValue && userIsNotAuthorised)
{
// return 401
}
// user is either authorised or has supplied a salesRepId or both
}
您还可以更改路由属性以匹配如下内容:
[HttpGet("customers/{salesRepId:int?}")]
public JsonResult Customers(int salesRepId = -1)
请注意,在本例中我必须提供默认选项。这将改变我们需要如何更改方法主体中的检查以匹配如下内容:
[HttpGet("customers/{salesRepId:int?}")]
public JsonResult Customers(int salesRepId = -1)
{
// userIsNotAuthorised is the name I'm giving to whatever
// whatever check you are making that the user is authorised
if (salesRepId == -1 && userIsNotAuthorised)
{
// return 401
}
// user is either authorised or has supplied a salesRepId or both
}
我个人更喜欢尽可能使用 Nullable 类型。这是因为在第二个示例中,我们依赖于 -1
(我们将其用作 magic number,这是一种反模式)。
您不需要 salesRepId
除了过滤。
当代表登录时,对 api/customers
的调用应该 return 管理员的所有客户和代表的所有客户。
调用 api/customers?salesRepId=123
应用相同的验证(可以通过 policy based authentcation 检查声明或范围),但过滤结果(属于一个代表的所有客户。
当管理员致电 api/customers?salesRepId=123
时,他收到的结果与销售代表致电 api/customers
或 api/customers?salesRepId=123
时收到的结果相同,但当销售代表致电 api/customers?salesRepId=456
时,他 returns 一个空结果(因为他的结果被 456 过滤结果为空)。
或者换句话说:如果用户是某种管理用户,控制器会将登录用户的 id 设置为销售代表过滤器。
这样您就不必以不同方式处理它,API 对每个用户的行为都相同。
不要忘记,RESTful 应用程序中的查询可以通过应用过滤来减少数据量。
或者,有两个路由操作的路由。 api/customers
具有我上面描述的行为和 api/salesrepresentative/123/customers
或 api/my/customers
(具体暗示它的范围缩小到登录用户)。这清楚地表明它是两种不同类型的资源。
第一个是所有客户的集合,而第二个是给定代表的所有客户。