标签:
授权即访问控制,它将判断用户在应用程序中对资源是否拥有相应的访问权限。
如,判断一个用户有查看页面的权限,编辑数据的权限,拥有某一按钮的权限等等。
一、用户权限模型
为实现一个较为灵活的用户权限数据模型,通常把用户信息单独用一个实体表示,用户权限信息用两个实体表示。
- 用户信息用 LoginAccount 表示,最简单的用户信息可能只包含用户名 loginName 及密码 password 两个属性。实际应用中可能会包含用户是否被禁用,用户信息是否过期等信息。
- 用户权限信息用 Role 与 Permission 表示,Role 与 Permission 之间构成多对多关系。Permission 可以理解为对一个资源的操作,Role 可以简单理解为 Permission 的集合。
- 用户信息与 Role 之间构成多对多关系。表示同一个用户可以拥有多个 Role,一个 Role 可以被多个用户所拥有。
权限声明及粒度
Shiro权限声明通常是使用以冒号分隔的表达式。就像前文所讲,一个权限表达式可以清晰的指定资源类型,允许的操作。同时,Shiro权限表达式支持简单的通配符,可以更加灵活的进行权限设置。
下面以实例来说明权限表达式。
可查询用户数据
User:view
可查询或编辑用户数据
User:view,edit
可对用户数据进行所有操作
User:*或 user
可编辑id为123的用户数据
User:edit:123
授权处理过程
认证通过后接受 Shiro 授权检查,授权验证时,需要判断当前角色是否拥有该权限。
只有授权通过,才可以访问受保护 URL 对应的资源,否则跳转到“未经授权页面”。
如果我们自定义Realm实现,比如我后面的例子中,自定义了ShiroDbRealm类,当访问被@RequiresPermissions注解的方法时,会先执行ShiroDbRealm.doGetAuthorizationInfo()进行授权。
- <span style="font-size:18px">@Controller
- @RequestMapping(value = "/user")
- public class UserController {
-
- @Resource(name="userService")
- private IUserService userService;
-
- @RequestMapping(value = "/register")
- @ResponseBody
- @RequiresPermissions("user:create")
- public boolean register(User user){
- return userService.register(user);
- }</span>
二、授权实现
Shiro支持三种方式实现授权过程:
1、基于编码的授权实现
1、基于权限对象的实现
创建org.apache.shiro.authz.Permission的实例,将该实例对象作为参数传递给Subject.isPermitted()进行验证。
- Permission printPermission = new PrinterPermission("laserjet4400n", "print");
- Subject currentUser = SecurityUtils.getSubject();
- if (currentUser.isPermitted(printPermission)) {
-
- } else {
-
- }
2、基于字符串的实现
相比笨重的基于对象的实现方式,基于字符串的实现便显得更加简洁。
- Subject currentUser = SecurityUtils.getSubject();
- if (currentUser.isPermitted("printer:print:laserjet4400n")) {
-
- } else {
-
- }
使用冒号分隔的权限表达式是org.apache.shiro.authz.permission.WildcardPermission默认支持的实现方式。
这里分别代表了资源类型:操作:资源ID
2、基于注解的授权实现
Shiro注解支持AspectJ、Spring、Google-Guice等,可根据应用进行不同的配置。
相关的注解:
@RequiresAuthentication
可以用户类/属性/方法,用于表明当前用户需是经过认证的用户。
- @RequiresAuthentication
- public void updateAccount(Account userAccount) {
-
-
- ...
- }
@RequiresPermissions
当前用户需拥有制定权限
- @RequiresPermissions("account:create")
- public void createAccount(Account account) {
-
-
- ...
- }
3、基于JSP TAG的授权实现
Shiro提供了一套JSP标签库来实现页面级的授权控制。
在使用Shiro标签库前,首先需要在JSP引入shiro标签:
- <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
hasRole标签
验证当前用户是否属于该角色
- <shiro:hasRole name="administrator">
- <a href="admin.jsp">Administer the system</a>
- </shiro:hasRole>
hasPermission标签
验证当前用户是否拥有制定权限
- <shiro:hasPermission name="user:create">
- <a href="createUser.jsp">Create a new User</a>
- </shiro:hasPermission>
三、Shiro授权的内部处理机制
1、在应用程序中调用授权验证方法(Subject的isPermitted*或hasRole*等)
2、Sbuject会委托应用程序设置的securityManager实例调用相应的isPermitted*或hasRole*方法。
3、接下来SecurityManager会委托内置的Authorizer的实例(默认是ModularRealmAuthorizer类的实例,类似认证实例)调用相应的授权方法。
4、每一个Realm将检查是否实现了相同的Authorizer 接口。然后,将调用Reaml自己的相应的授权验证方法。
四、授权代码
UserController:处理用户登录后的请求(注册)
- package org.shiro.demo.controller;
-
- import javax.annotation.Resource;
-
- import org.apache.shiro.authz.annotation.RequiresPermissions;
- import org.apache.shiro.authz.annotation.RequiresRoles;
- import org.shiro.demo.entity.User;
- import org.shiro.demo.service.IUserService;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.ResponseBody;
-
- @Controller
- @RequestMapping(value = "/user")
- public class UserController {
-
- @Resource(name="userService")
- private IUserService userService;
-
-
- @RequestMapping(value = "/register")
- @ResponseBody
- @RequiresPermissions("user:create")
- public boolean register(User user){
- return userService.register(user);
- }
-
-
- @RequestMapping(value = "/toRegister")
- @RequiresRoles("administrator")
- public String toRegister(){
- return "/system/user/register";
- }
- }
ShiroDbRealm:自定义的指定Shiro验证用户授权的类
- <span style="font-size:18px">packageorg.shiro.demo.service.realm;
-
- importjava.util.ArrayList;
- importjava.util.List;
-
- importjavax.annotation.Resource;
-
- importorg.apache.commons.lang.StringUtils;
- importorg.apache.shiro.authc.AuthenticationException;
- importorg.apache.shiro.authc.AuthenticationInfo;
- importorg.apache.shiro.authc.AuthenticationToken;
- importorg.apache.shiro.authc.SimpleAuthenticationInfo;
- importorg.apache.shiro.authc.UsernamePasswordToken;
- importorg.apache.shiro.authz.AuthorizationException;
- importorg.apache.shiro.authz.AuthorizationInfo;
- importorg.apache.shiro.authz.SimpleAuthorizationInfo;
- importorg.apache.shiro.realm.AuthorizingRealm;
- importorg.apache.shiro.subject.PrincipalCollection;
- importorg.shiro.demo.entity.Permission;
- importorg.shiro.demo.entity.Role;
- importorg.shiro.demo.entity.User;
- importorg.shiro.demo.service.IUserService;
-
- publicclass ShiroDbRealm extends AuthorizingRealm{
-
- privateIUserService userService;
-
- publicvoid setUserService(IUserService userService) {
- this.userService= userService;
- }
-
-
- protectedAuthorizationInfo doGetAuthorizationInfo(
- PrincipalCollectionprincipals) {
-
- Stringaccount = (String) super.getAvailablePrincipal(principals);
-
- List<String>roles = new ArrayList<String>();
- List<String>permissions = new ArrayList<String>();
-
- Useruser = userService.getByAccount(account);
-
- if(user!= null){
- if(user.getRoles() != null && user.getRoles().size() > 0) {
- for(Role role : user.getRoles()) {
- roles.add(role.getName());
-
- if(role.getPmss() != null && role.getPmss().size() > 0) {
-
- for(Permission pmss : role.getPmss()) {
- if(!StringUtils.isEmpty(pmss.getPermission())){
- permissions.add(pmss.getPermission());
- }
- }
- }
- }
- }
- }else{
- thrownew AuthorizationException();
- }
-
- SimpleAuthorizationInfoinfo = new SimpleAuthorizationInfo();
- info.addRoles(roles);
- info.addStringPermissions(permissions);
-
- returninfo;
-
- }
-
- }</span>
shiro中基于注解实现的权限认证过程
标签:
原文地址:http://www.cnblogs.com/lzlblogs/p/5973535.html