用户授权(权限管理)
Masonite 也提供一种简单的方式授权用户对资源操作。基于两个概念:Gates 和 Policies。Gates 顾名思义就是一种授权安检,在操作资源前需要校验用户是否有权访问。Policies 是一种围绕模型进行分组授权逻辑方式。
门(Gates)
Gates 是简单的可调用对象,它将定义用户是否被授权执行给定的操作。可使用方便的 Gate 门面来轻松操纵 Gates 。
注册门
门将用户实例作为第一个参数,并可能接收额外的参数,例如模型实例。你需要在服务提供者的 boot() 方法中定义 Gates 。
在下面的示例中,我们正在添加门以验证用户是否可以创建和更新帖子。如果用户是管理员,则可以创建帖子,并且只能更新他们自己创建的帖子。
from masonite.facades import Gate
class MyAppProvider(Provider):
    def boot(self):
        Gate.define("create-post", lambda user: user.is_admin)
        Gate.define("update-post", lambda user, post: post.user_id == user.id)你可以使用 has() 来检查门是否存在或已注册,它将返回一个布尔值:
Gate.has("create-post")提示:如果使用未知的门,则会引发
GateDoesNotExist异常。
授权操作
然后,在代码的任何位置(通常在控制器中),你可以使用这些门来检查 当前已认证用户 是否被授权执行门所定义的给定操作。
Gates 使用不同的方法来执行验证:allows()、denies()、none()、any()、authorize()、inspect()。
allows()、denies()、none() 和 any() 返回一个布尔值,表示用户是否被授权。
if not Gate.allows("create-post"):
    return response.redirect("/")
# ...
post = Post.find(request.input("id"))
if Gate.denies("update-post", post):
    return response.redirect("/")
# ...
Gate.any(["delete-post", "update-post"], post)
# ...
Gate.none(["force-delete-post", "restore-post"], post)authorize() 不返回布尔值,而是会引发一个 AuthorizationException 异常,该异常将呈现为带有 403 状态码的 HTTP 响应。
Gate.authorize("update-post", post)
# 如果程序执行到这里,那么用户已被授权。
# 否则,将会抛出一个异常,并返回一个状态码为 403 的错误信息:"Action not authorized"。最后,为了更好地控制授权检查,你可以使用 inspect() 分析响应:
response = Gate.inspect("update-post", post)
if response.allowed():
     # 做一些事情
else:
     # 没有授权,但我们可以访问消息。
     Session.flash("errors", response.message())通过用户模型
可以将 Authorizes 类添加到用户模型中,以允许快速权限检查:
from masonite.authentication import Authenticates
from masonite.authorization import Authorizes
class User(Model, Authenticates, Authorizes):
    #..现在,User 实例上将提供流畅的授权 API:
user.can("delete-post", post)
user.cannot("access-admin")
user.can_any(["delete-post", "force-delete-post"], post)所有这些方法都接收门名称作为第一个参数,然后根据需要添加一些其他参数。
使用给定的用户
你可以在 Gate 门面上使用 for_user() 方法来针对给定的用户进行验证,而不是针对已认证用户。
from masonite.facades import Gate
user = User.find(1)
Gate.for_user(user).allows("create-post")门钩子
在门授权过程中,可以触发 before 和 after 钩子。
可以按以下方式添加 before 钩子:
# 在这里,管理员用户将始终基于此响应的布尔值进行授权。
Gate.before(lambda user, permission : user.role == "admin")after 钩子的工作方式相同:
Gate.after(lambda user, permission, result : user.role == "admin")如果 after 回调返回一个值,它将优先于门结果检查。
策略(Policies)
策略是围绕特定模型组织授权逻辑的类。
创建策略
可以运行以下命令:
$ python craft policy AccessAdmin也可以使用 --model 标志创建一个具有一组预定义门的策略:
$ python craft policy Post --model模型策略带有我们可以在模型上执行的常见操作:
from masonite.authorization import Policy
class PostPolicy(Policy):
    def create(self, user):
        return False
    def view_any(self, user):
        return False
    def view(self, user, instance):
        return False
    def update(self, user, instance):
        return False
    def delete(self, user, instance):
        return False
    def force_delete(self, user, instance):
        return False
    def restore(self, user, instance):
        return False你可以自由添加任何其他方法到你的策略中:
from masonite.authorization import Policy
class PostPolicy(Policy):
    #.. 
    def publish(self, user):
        return user.email == "admin@masonite.com"
注册策略
然后在你的服务提供者中(如定义门一样),你应该注册策略并将其绑定到一个模型:
from masonite.facades import Gate
from app.models.Post import Post
from app.models.User import User
from app.policies.PostPolicy import PostPolicy
from app.policies.UserPolicy import UserPolicy
class MyAppProvider(Provider):
    #..
    def register(self):
        Gate.register_policies(
            [(Post, PostPolicy), (User, UserPolicy)],
        )对于 Post 模型的示例策略可能如下所示:
from masonite.authorization import Policy
class PostPolicy(Policy):
    def create(self, user):
        return user.email == "idmann509@gmail.com"
    def view(self, user, instance):
        return True
    def update(self, user, instance):
        return user.id == instance.user_id提示:如果使用了未知的策略,则会引发
PolicyDoesNotExist异常。
授权操作
然后,你可以使用 Gate 门面方法来授权在你的策略中定义的操作。使用先前定义的PostPolicy ,我们可以进行以下调用:
from masonite.facades import Gate
post = Post.find(1)
Gate.allows("update", post)
Gate.denies("view", post)
Gate.allows("force_delete", post)create() 或 view_any() 方法不需要模型实例,因此应该提供模型类,以便 Gate 机制可以推断出这些方法属于哪个策略。
Gate.allows("create", Post)
Gate.allows("view_any", Post)本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
 
           Masonite 中文文档
 Masonite 中文文档 
         
         
         
         
             
             关于 LearnKu
                关于 LearnKu
               
                     
                     
                     粤公网安备 44030502004330号
 粤公网安备 44030502004330号