【Shiro】Shiro从小白到大神(三)-权限认证(授权)-2

简介: 【Shiro】Shiro从小白到大神(三)-权限认证(授权)-2

JSP标签授权


必须添加shiro-web.jar


在jsp页面中引入:


<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>


guest标签


用户没有身份验证时显示相应信息,即游客访问信息

例如:


<shiro:guest>
    Hi there!  Please <a href="login.jsp">Login</a> or <a href="signup.jsp">Signup</a> today!
</shiro:guest>


在这里标签内的文字,如果用户没有登录才会显示出来,也就是游客


user标签


只有在当前Subject被认为是“用户”时,用户标记才会显示其包装内容。

在这个上下文中,“用户”被定义为一个具有已知身份的主题,要么是成功的身份验证,要么是来自“记住我”的服务。

注意,这个标记与经过身份验证的标记有语义上的不同,它比这个标记更加严格。

例如:


<shiro:user>
    Welcome back John!  Not John? Click <a href="login.jsp">here<a> to login.
</shiro:user>


user标签和guest标签逻辑相反


authenticated标签


仅当当前用户在当前会话中成功验证时才显示正文内容。

它比“用户”标签更具限制性。它在逻辑上与“notAuthenticated”标记相反。

只有在当前Subject在当前会话中成功验证的情况下,经过身份验证的标记才会显示其包装内容。

它是一个比用户更严格的标记,用来保证敏感工作流中的标识。也就是说,通过记住我登录的无法访问到!!!

例如:


<shiro:authenticated>
    <a href="updateAccount.jsp">Update your contact information</a>.
</shiro:authenticated>


notAuthenticated标签


如果当前Subject在当前会话中尚未成功验证,则未验证标记将显示其包装内容。

也就是用户没有身份验证通过,即没有调用Subject.login进行登录,包括记住我自动登录的也属于未进行身份验证这个notAuthenticated标签!


例如:


<shiro:notAuthenticated>
    Please <a href="login.jsp">login</a> in order to update your credit card information.
</shiro:notAuthenticated>


principal标签


输出用户信息,会调用toString()方法

例如:


Hello, <shiro:principal/>, how are you today?


相当于调用以下代码:


Hello, <%= SecurityUtils.getSubject().getPrincipal().toString() %>, how are you today?


通过类型


如果你不想获取所有的,比如在用户名和用户id之间,我想获取用户id,可以通过下面这种方式:


User ID: <principal type="java.lang.Integer"/>


等同于:


User ID: <%= SecurityUtils.getSubject().getPrincipals().oneByType(Integer.class).toString() %>


通过属性名


但是,当遇到复杂的情况时,上面的就不行了,毕竟可能不止一个Integer,这个时候就可以通过属性名了。

通过getter方法获取的

例如:


Hello, <shiro:principal property="firstName"/>, how are you today?


相当于下面的代码:


Hello, <%= SecurityUtils.getSubject().getPrincipal().getFirstName().toString() %>, how are you today?


或者说,可以结合type属性:


Hello, <shiro:principal type="com.foo.User" property="firstName"/>, how are you today?


也就是如下代码的逻辑:


Hello, <%= SecurityUtils.getSubject().getPrincipals().oneByType(com.foo.User.class).getFirstName().toString() %>, how are you today?


hasRole标签


只有当当前Subject被分配指定角色时,hasRole标记才会显示其包装内容


例如:


<shiro:hasRole name="administrator">
    <a href="admin.jsp">Administer the system</a>
</shiro:hasRole>


lacksRole标签


如果当前Subject没有分配指定的角色,则将显示其包装内容。


<shiro:lacksRole name="administrator">
    Sorry, you are not allowed to administer the system.
</shiro:lacksRole>


lacksRole标签与hasRole标签的逻辑相反。


hasAnyRole标签


如果当前Subject从一个由逗号分隔的角色名称列表中具有了任一指定的角色,那么hasAnyRole标记将显示其包装内容。


<shiro:hasAnyRoles name="developer, project manager, administrator">
    You are either a developer, project manager, or administrator.
</shiro:hasAnyRoles>


只要有其中一个角色,即显示主体内容


hasPermission标签


如果当前Subject有权限则显示其包装的内容


<shiro:hasPermission name="user:create">
    <a href="createUser.jsp">Create a new User</a>
</shiro:hasPermission>


lacksPermission标签


如果当前Subject没有该权限则显示其包装的内容


<shiro:lacksPermission name="user:delete">
    Sorry, you are not allowed to delete user accounts.
</shiro:lacksPermission>


lacksPermission标签与hasPermission标签的逻辑相反


深入理解Apache Shiro的Permissions


通配符的权限


单个权限: 直接起一个字符串名即可


例如: queryPrinter权限-查询权限


subject.isPermitted("queryPrinter")


基本等同于:


subject.isPermitted( new WildcardPermission("queryPrinter") )


第二种方式基本不用,用第一种方式即可


多个权限: 通配符权限支持多个级别或部分的概念。


下面使用”:”用于分隔权限字符串下一部分的特殊字符。


printer:query
printer:print
printer:manage


即可配置多个权限


也可以用多值来配置:


printer:print,query


验证查询权限:


subject.isPermitted("printer:query")


单个资源的所有权限


比如我们有这些权限:


printer:query,print,manage


相当于:


printer:*


使用第二种方法使用通配符比显式地列出动作要更好,因为如果以后向应用程序添加了一个新操作,则不需要更新在该部分中使用通配符的权限。


所有资源的某个权限


还可以在通配符权限字符串的任何部分使用通配符令牌


*:view


所有资源的view权限

也就是说对“foo:view”(或其他的:view)的任何权限检查将返回true


实例级别的权限控制


通配符权限的另一个常见用法是建立实例级访问控制列表。

在这个权限中,您将使用三个部分——第一个是域,第二个是动作,第三个是被执行的实例(标识)。


单个实例的单个权限


printer:query:lp7200
printer:print:epsoncolor


比如你拥有printer的query权限,打印机的id为lp7200,也就是拥有这类printer的query权限


如果您将这些权限授予用户,那么它们就可以在特定的实例上执行特定的行为。然后你可以在代码中做一个检查:


if ( SecurityUtils.getSubject().isPermitted("printer:query:lp7200") {
    // Return the current jobs on printer lp7200 }
}


所有实例的单个权限


printer:print:*


也就是说,具有所有printer的print权限,相当于前面的单个资源的多个权限


所有实例的所有权限


printer:*:*


单个实例的所有权限


printer:*:lp7200


单个实例的多个权限


printer:query,print:lp7200


query和print之间用逗号隔开

在实际开发中,基本上用不到实例级别的权限控制


关于权限分配的最后一件事是:末尾丢失的部分意味着用户可以访问与该部分对应的所有值。换句话说,


printer:print

就相当于:

printer:print:*


printer

单个权限相当于

printer:*:*


但是注意!


printer:lp7200

printer:*:lp7200

是不同的!!!


因为这不是末尾的*


检查权限


虽然权限分配使用通配符构造相当多(“printer:*”=打印到任何printer),但在运行时的权限检查应该始终基于可能的最特定的权限字符串。

比如:如果用户有一个用户界面,他们想要打印一个文档到lp7200打印机,你应该检查用户是否允许执行这个代码


if ( SecurityUtils.getSubject().isPermitted("printer:print:lp7200") ) {
    //print the document to the lp7200 printer }
}


这个检查非常具体,并且明确地反映了用户在那个时候正在尝试做什么。

但是,如下代码是不对的:


if ( SecurityUtils.getSubject().isPermitted("printer:print") ) {
    //print the document }
}


因为第二个示例说“您必须能够打印到任何打印机,以便执行以下代码块”。但请记住,“printer:print”等同于“printer:print:*”!


因此,这是一个不正确的检查。

如果当前用户没有能力打印到任何打印机,但他们确实有打印的能力,比如lp7200和epsoncolor打印机。

然而,上面的第二个例子永远不会允许他们打印到lp7200打印机,即使他们已经获得了这种能力!


因此,经验法则是在执行权限检查时使用最特殊的权限字符串。

当然,如果您真的只想执行代码块,如果用户被允许打印到任何打印机(可能),那么第二个方法可能是应用程序中的另一个有效的检查。

您的应用程序将决定什么检查是有意义的,但是一般来说,越具体越好。


为什么运行时权限检查应该尽可能具体,但是权限分配可以更通用一些呢?

这是因为权限检查是由隐含逻辑计算的,而不是平等检查。


也就是说,如果用户被分配给”user:“权限,这意味着用户可以执行”user:view”操作。字符串”user:“显然不等于”user:view”,但前者暗示后者。”user:*”描述了由”user:view”定义的功能的超集。


为了支持隐含规则,所有权限都被翻译到实现org.apache.shiro.authz的对象实例的权限接口中。

这就是说,隐含逻辑可以在运行时执行,而且隐含逻辑通常比简单的字符串等式检查更复杂。

本文档中描述的所有通配符行为实际上都是由org.apache.shiro.authz.permission.WildcardPermission类实现


下面是一些通配符的权限字符串,它显示了访问的含义:


user:*


暗指还能删除用户的能力:


user:delete


但是:


user:*:12345


也就是说,还可以使用实例12345更新用户帐户:


user:update:12345
printer
暗示了打印机的任何功能,比如:
printer:print


授权流程




授权其实就是查看有没有权限,有就授权给它


授权步骤:


Step 1: Application or framework code invokes any of the Subject hasRole*, checkRole*, isPermitted*, or checkPermission* method variants, passing in whatever permission or role representation is required.


Step 2: The Subject instance, typically a DelegatingSubject (or a subclass) delegates to the application’s SecurityManager by calling the securityManager’s nearly identical respective hasRole*, checkRole*, isPermitted*, or checkPermission* method variants (the securityManager implements the org.apache.shiro.authz.Authorizer interface, which defines all Subject-specific authorization methods).


Step 3: The SecurityManager, being a basic ‘umbrella’ component, relays/delegates to its internal org.apache.shiro.authz.Authorizer instance by calling the authorizer’s respective hasRole*, checkRole*, isPermitted*, or checkPermission* method. The authorizer instance is by default a ModularRealmAuthorizer instance, which supports coordinating one or more Realm instances during any authorization operation.


Step 4: Each configured Realm is checked to see if it implements the same Authorizer interface. If so, the Realm’s own respective hasRole*, checkRole*, isPermitted*, or checkPermission* method is called.


有兴趣的可以去官网看看:http://shiro.apache.org/authorization.html



目录
相关文章
|
6月前
|
数据库
shiro认证和授权
shiro认证和授权
52 3
|
6月前
|
Java 数据安全/隐私保护
Shiro - 授权那些事
Shiro - 授权那些事
51 0
|
6月前
|
缓存 安全 数据安全/隐私保护
Shiro - 认证那些事
Shiro - 认证那些事
43 0
|
JSON 前端开发 数据格式
SpringSecurity基础-认证授权结果处理
在传统的应用中,认证成功后页面需要跳转到认证成功页面或者跳转到个人中心页,但是在前后端分离的项目通常是使用Ajax请求完成认证,这时候我们需要返回一个JSON结果告知前端认证结果,然后前端自行跳转页面。 要做到上述功能,我们需要自定义认证成功处理器实现AuthenticationSuccessHandler接口复写 onAuthenticationSuccess方法,该方法其中一个参数是Authentication ,他里面封装了认证信息,用户信息UserDetails等,我们需要在这个方法中使用Response写出json数据即可
134 0
|
JSON 前端开发 数据格式
六.SpringSecurity基础-认证授权结果处理
SpringSecurity基础-认证授权结果处理
|
Java 数据安全/隐私保护
【Shiro】1、Shiro实现登录授权认证功能(下)
之前在 SSM 项目中使用过 shiro,发现 shiro 的权限管理做的真不错,但是在 SSM 项目中的配置太繁杂了,于是这次在 SpringBoot 中使用了 shiro,下面一起看看吧
135 0
|
Java 数据安全/隐私保护
【Shiro】1、Shiro实现登录授权认证功能(中)
之前在 SSM 项目中使用过 shiro,发现 shiro 的权限管理做的真不错,但是在 SSM 项目中的配置太繁杂了,于是这次在 SpringBoot 中使用了 shiro,下面一起看看吧
130 0
|
安全 Java 数据库连接
【Shiro】1、Shiro实现登录授权认证功能(上)
之前在 SSM 项目中使用过 shiro,发现 shiro 的权限管理做的真不错,但是在 SSM 项目中的配置太繁杂了,于是这次在 SpringBoot 中使用了 shiro,下面一起看看吧
311 0
|
网络安全 数据库 数据安全/隐私保护
Shiro自定义Realm实现认证和授权(五)下
Shiro自定义Realm实现认证和授权(五)
158 0
Shiro自定义Realm实现认证和授权(五)下
|
缓存 数据库 数据安全/隐私保护
Shiro自定义Realm实现认证和授权(五)上
Shiro自定义Realm实现认证和授权(五)
345 0
Shiro自定义Realm实现认证和授权(五)上