Shiro学习笔记——权限与授权

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012525096/article/details/82683594

概念

  • 授权:访问控制,即在应用中控制谁访问哪些资源。
  • 主体: 访问应用的用户,Shiro里面的Subject代表该用户。
  • 资源:Web应用里面体现为用户可以访问的URL。
  • 权限:应用中,用户能不能访问某个资源。
  • 角色:权限的集合。

授权方式

  1. 编程式:通常写if/else授权代码块完成。
if(subject.hasRole("admin")){
    //有权限
}else{
    //无权限
}
  1. 注解式(常用):通常在执行的Java方法上放置相应的注解完成,没有权限将抛出响应的异常。
@RequiresRoles("admin")
public void hello(){
    //有权限
}
  1. JSP/GSP标签:在JSP/GSP页面通过相应的标签完成,隐藏没有权限的资源。
<shiro:hasRole name="admin">
    <!-- 有权限 -->
</shiro:hasRole>

拦截器

默认的过滤器,共有一下几种:
这里写图片描述
身份验证相关的过滤器:
这里写图片描述
授权相关的:
这里写图片描述
其他:
这里写图片描述

配置权限

在applicationContext.xml中配置权限。

    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <property name="loginUrl" value="/login.jsp"/>
        <property name="successUrl" value="/list.jsp"/>
        <property name="unauthorizedUrl" value="/unauthorized.jsp"/>

        <!--  
            配置哪些页面需要受保护. 
            以及访问这些页面需要的权限. 
            1). anon 可以被匿名访问
            2). authc 必须认证(即登录)后才可能访问的页面. 
            3). logout 登出.
            4). roles 角色过滤器
        -->
        <property name="filterChainDefinitions">
            <value>
                /login.jsp = anon
                /shiro/login = anon
                /shiro/logout = logout

                /user.jsp = roles[user]
                /admin.jsp =  roles[admin]

                # everything else requires authentication:
                /** = authc
            </value>
        </property>
    </bean>

其中,user.jsp需要具有user的角色,admin.jsp需要具有admin的角色,才可以访问,否则跳转至unauthorized.jsp


授权Realm

(1)授权需要继承AuthorizingRealm,并实现其doGetAuthorizationInfo方法。
(2)AuthorizingRealm继承自AuthenticatingRealm,但没有实现AuthenticatingRealm中的doGetAuthenticationInfo方法,所以认证和授权只需要继承AuthorizingRealm就可以了,同时实现他的两个抽象方法即可。(Authorization授权,Authentication认证)

实现授权Realm

使Realm继承自AuthorizingRealm,实现doGetAuthorizationInfo,就可以完成授权操作,实现doGetAuthenticationInfo,就可以完成认证操作。
实现如下:

public class ShiroRealm extends AuthorizingRealm {

    /*
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("[FirstShiroRealm] doGetAuthenticationInfo: ");

        // 1. 把AuthenticationToken 转换为UsernamePasswordToken
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;

        // 2. 把UsernamePasswordToken 中来获取username
        String username = upToken.getUsername();

        // 3. 调用数据库的方法,从数据库中查询username 对应的用户记录.
        System.out.println("从数据库中获   取username:" + username + " 所对应的用户信息.");

        // 4.若用户不存在,则可以抛出UnknownAccountException 异常
        if ("unknown".equals(username)) {
            throw new UnknownAccountException("用户不存在");
        }

        // 5.根据用户信息的情况,决定是否需要抛出其他的AuthenticationException 异常.
        if ("monster".equals(username)) {
            throw new LockedAccountException("用户被锁定");
        }

        // 6.根据用户的情况,来构建AuthenticationInfo 对象并返回.
        // 通常使用的实现类是SimpleAuthenticationInfo
        // 以下信息是从数据库中获取的.
        // (1)principal:认证的实体信息,可以是username,也可以是数据表对应的用户的实体类对象
        Object principal = username;
        // (2)credentials:密码.
        Object credentials = null;// "fc1709d0a95a6be30bc5926fdb7f22f4";
        if ("admin".equals(username)) {
            credentials = "038bdaf98f2037b31f1e75b5b4c9b26e";
        } else if ("user".equals(username)) {
            credentials = "098d2c478e9c11555ce2823231e02ec1";
        }
        // (3)realmName:当前realm 对象的name,调用父类的getName()方法
        String realmName = getName();
        // (4)盐值:
        ByteSource credentialsSalt = ByteSource.Util.bytes(username);
        // AuthenticationInfo info = new SimpleAuthenticationInfo(principal,
        // credentials, realmName);
        AuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName);
        return info;
    }

    /*
     * 授权,会被shiro回调的方法
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //1.从PrincipalCollection中获取登录用户的信息
        Object principal = principals.getPrimaryPrincipal();

        //2.利用登录的用户信息来获取当前用户的角色或权限(可能需要查询数据库)
        Set<String> roles = new HashSet<>();
        roles.add("user");
        if("admin".equals(principal)) {
            roles.add("admin");
        }


        //3.创建 SimpleAuthorizationInfo,并设置其roles属性
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);

        //4.返回SimpleAuthorizationInfo对象.
        return info;
    }

}

说明:doGetAuthorizationInfo方法是进行授权的方法,返回值就是授权信息。
授权过程:
(1)从PrincipalCollection中获取登录用户的信息
(2)利用登录的用户信息来获取当前用户的角色或权限(可能需要查询数据库)
(3)创建 SimpleAuthorizationInfo,并设置其roles属性,代表其角色(权限)集合。
(4)返回SimpleAuthorizationInfo对象。

猜你喜欢

转载自blog.csdn.net/u012525096/article/details/82683594