shiro分布式控制登录状态_Shiro(一)

本篇文章参考大神的文章,总结而来。附赠大神帖子地址。https://jinnianshilongnian.iteye.com/blog/2018398

什么是Shiro?

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。

Shiro的作用

Shiro可以非常容易的开发出足够好的应用,其不仅可以用在JavaSE环境,也可以用在JavaEE环境。Shiro可以帮助我们完成:认证、授权、加密、会话管理、与Web集成、缓存等。这不就是我们想要的嘛,而且Shiro的API也是非常简单;其基本功能点如下图所示:

009e47d961a8e5c825abfe178e05f44e.png

Authentication:身份认证/登录,验证用户是不是拥有相应的身份;

Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;

Session Manager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的;

Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;

Web Support:Web支持,可以非常容易的集成到Web环境;

Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;

Concurrency:shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;

Testing:提供测试支持;

Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;

Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。

从外部来看Shiro

dfb812b353c5b6860dcad4b337c07028.png

可以看到:应用代码直接交互的对象是Subject,也就是说Shiro的对外API核心就是Subject;

Subject:主体,代表了当前“用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject,如网络爬虫,机器人等;即一个抽象概念;所有Subject都绑定到SecurityManager,与Subject的所有交互都会委托给SecurityManager;可以把Subject认为是一个门面;SecurityManager才是实际的执行者;

SecurityManager:安全管理器;即所有与安全有关的操作都会与SecurityManager交互;且它管理着所有Subject;可以看出它是Shiro的核心,它负责与后边介绍的其他组件进行交互,如果学习过SpringMVC,你可以把它看成DispatcherServlet前端控制器;

Realm:域,Shiro从从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。

就是说对于我们而言,最简单的一个Shiro应用流程:

1、应用代码通过Subject来进行认证和授权,而Subject又委托给SecurityManager;

2、我们需要给Shiro的SecurityManager注入Realm,从而让SecurityManager能得到合法的用户及其权限进行判断。

从内部来看Shiro

eb8ffc043655445ac9e40d2159d5ef51.png

Subject:主体,可以看到主体可以是任何可以与应用交互的“用户”;

SecurityManager:相当于SpringMVC中的DispatcherServlet或者Struts2中的FilterDispatcher;是Shiro的心脏;所有具体的交互都通过SecurityManager进行控制;它管理着所有Subject、且负责进行认证和授权、及会话、缓存的管理。

Authenticator:认证器,负责主体认证的,这是一个扩展点,如果用户觉得Shiro默认的不好,可以自定义实现;其需要认证策略(Authentication Strategy),即什么情况下算用户认证通过了;

Authrizer:授权器,或者访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中的哪些功能;

Realm:可以有1个或多个Realm,可以认为是安全实体数据源,即用于获取安全实体的;可以是JDBC实现,也可以是LDAP实现,或者内存实现等等;由用户提供;注意:Shiro不知道你的用户/权限存储在哪及以何种格式存储;所以我们一般在应用中都需要实现自己的Realm;

SessionManage:如果写过Servlet就应该知道Session的概念,Session呢需要有人去管理它的生命周期,这个组件就是SessionManager;而Shiro并不仅仅可以用在Web环境,也可以用在如普通的JavaSE环境、EJB等环境;所有呢,Shiro就抽象了一个自己的Session来管理主体与应用之间交互的数据;这样的话,比如我们在Web环境用,刚开始是一台Web服务器;接着又上了台EJB服务器;这时想把两台服务器的会话数据放到一个地方,这个时候就可以实现自己的分布式会话(如把数据放到Memcached服务器);

SessionDAO:DAO大家都用过,数据访问对象,用于会话的CRUD,比如我们想把Session保存到数据库,那么可以实现自己的SessionDAO,通过如JDBC写到数据库;比如想把Session放到Memcached中,可以实现自己的Memcached SessionDAO;另外SessionDAO中可以使用Cache进行缓存,以提高性能;

CacheManager:缓存控制器,来管理如用户、角色、权限等的缓存的;因为这些数据基本上很少去改变,放到缓存中后可以提高访问的性能

Cryptography:密码模块,Shiro提高了一些常见的加密组件用于如密码加密/解密的。

第一个Shiro的HelloWord

导入jar包

  • shiro-all-1.3.2.jar
  • log4j-1.2.15.jar
  • slf4j-api-1.6.1.jar
  • slf4j-log4j12-1.6.1.jar

配置文件

# =============================================================================
# Quickstart INI Realm configuration
#
# For those that might not understand the references in this file, the
# definitions are all based on the classic Mel Brooks' film "Spaceballs". ;)
# =============================================================================

# -----------------------------------------------------------------------------
# Users and their assigned roles
#
# Each line conforms to the format defined in the
# org.apache.shiro.realm.text.TextConfigurationRealm#setUserDefinitions JavaDoc
# -----------------------------------------------------------------------------
[users]
# user 'root' with password 'secret' and the 'admin' role
root = secret, admin
# user 'guest' with the password 'guest' and the 'guest' role
guest = guest, guest
# user 'presidentskroob' with password '12345' ("That's the same combination on
# my luggage!!!" ;)), and role 'president'
presidentskroob = 12345, president
# user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz'
darkhelmet = ludicrousspeed, darklord, schwartz
# user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz'
lonestarr = vespa, goodguy, schwartz

# -----------------------------------------------------------------------------
# Roles with assigned permissions
# 
# Each line conforms to the format defined in the
# org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc
# -----------------------------------------------------------------------------
[roles]
# 'admin' role has all permissions, indicated by the wildcard '*'
admin = *
# The 'schwartz' role can do anything (*) with any lightsaber:
schwartz = lightsaber:*
# The 'goodguy' role is allowed to 'delete' (action) the user (type) with
# license plate 'zhangsan' (instance specific id)
#user可以删除zhangsan
goodguy = user:delete:zhangsan

配置文件中配置了简单的几个用户和角色,当然实际开发中不可能将用户信息放入配置文件,都是从数据库动态获取用户信息。这里只是简单的测试。

测试代码:

package cn.xyl.shiro;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;



public class HelloWord {

    private static final transient Logger log = LoggerFactory.getLogger(HelloWord.class);
    public static void main(String[] args) {

        // The easiest way to create a Shiro SecurityManager with configured
        // realms, users, roles and permissions is to use the simple INI config.
        // We'll do that by using a factory that can ingest a .ini file and
        // return a SecurityManager instance:

        // Use the shiro.ini file at the root of the classpath
        // (file: and url: prefixes load from files and urls respectively):
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        SecurityManager securityManager = factory.getInstance();

        // for this simple example quickstart, make the SecurityManager
        // accessible as a JVM singleton. Most applications wouldn't do this
        // and instead rely on their container configuration or web.xml for
        // webapps. That is outside the scope of this simple quickstart, so
        // we'll just do the bare minimum so you can continue to get a feel
        // for things.
        //绑定给SecurityUtils    这是一个全局设置,设置一次即可;
        SecurityUtils.setSecurityManager(securityManager);

        // Now that a simple Shiro environment is set up, let's see what you can do:

        // get the currently executing user:
        // 获取当前的 Subject. 调用 SecurityUtils.getSubject();   
        //通过SecurityUtils得到Subject,其会自动绑定到当前线程
        Subject subject = SecurityUtils.getSubject();

        // Do some stuff with a Session (no need for a web or EJB container!!!)
        // 测试使用 Session
        // 获取 Session: Subject#getSession()
        Session session = subject.getSession();
        session.setAttribute("someKey", "aValue");
        String value = (String) session.getAttribute("someKey");
        if (value.equals("aValue")) {
            log.info("---> Retrieved the correct value! [" + value + "]");
        }

        // let's login the current user so we can check against roles and permissions:
        // 测试当前的用户是否已经被认证. 即是否已经登录.
        // 调动 Subject 的 isAuthenticated()
        if (!subject.isAuthenticated()) {
            // 把用户名和密码封装为 UsernamePasswordToken 对象
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
            // rememberme
            token.setRememberMe(true);
            try {
                // 执行登录.
                subject.login(token);
            }
            // 若没有指定的账户, 则 shiro 将会抛出 UnknownAccountException 异常.
            catch (UnknownAccountException uae) {
                log.info("----> There is no user with username of " + token.getPrincipal());
                return;
            }
            // 若账户存在, 但密码不匹配, 则 shiro 会抛出 IncorrectCredentialsException 异常。
            catch (IncorrectCredentialsException ice) {
                log.info("----> Password for account " + token.getPrincipal() + " was incorrect!");
                return;
            }
            // 用户被锁定的异常 LockedAccountException
            catch (LockedAccountException lae) {
                log.info("The account for username " + token.getPrincipal() + " is locked.  "
                        + "Please contact your administrator to unlock it.");
            }
            // ... catch more exceptions here (maybe custom ones specific to your
            // application?
            // 所有认证时异常的父类.
            catch (AuthenticationException ae) {
                // unexpected condition? error?
            }
        }

        // say who they are:
        // print their identifying principal (in this case, a username):
        log.info("----> User [" + subject.getPrincipal() + "] logged in successfully.");

        // test a role:
        // 测试是否有某一个角色. 调用 Subject 的 hasRole 方法.
        if (subject.hasRole("schwartz")) {
            log.info("----> May the Schwartz be with you!");
        } else {
            log.info("----> Hello, mere mortal.");
            return;
        }

        // test a typed permission (not instance-level)
        // 测试用户是否具备某一个行为. 调用 Subject 的 isPermitted() 方法。
        if (subject.isPermitted("lightsaber:weild")) {
            log.info("----> You may use a lightsaber ring.  Use it wisely.");
        } else {
            log.info("Sorry, lightsaber rings are for schwartz masters only.");
        }

        // a (very powerful) Instance Level permission:
        // 测试用户是否具备某一个行为.
        if (subject.isPermitted("user:delete:zhangsan")) {
            log.info("----> You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  "
                    + "Here are the keys - have fun!");
        } else {
            log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
        }

        // all done - log out!0
        // 执行登出. 调用 Subject 的 Logout() 方法.
        System.out.println("---->" + subject.isAuthenticated());

        subject.logout();

        System.out.println("---->" + subject.isAuthenticated());

        System.exit(0);
    }

}

测试代码中演示了使用Shiro的基本流程

  1. 首先通过new IniSecurityManagerFactory并指定一个ini配置文件来创建一个SecurityManager工厂;
  2. 接着获取SecurityManager并绑定到SecurityUtils,这是一个全局设置,设置一次即可;
  3. 通过SecurityUtils得到Subject,其会自动绑定到当前线程;如果在web环境在请求结束时需要解除绑定;然后获取身份验证的Token,如用户名/密码;
  4. 调用subject.login方法进行登录,其会自动委托给SecurityManager.login方法进行登录;
  5. 如果身份验证失败请捕获AuthenticationException或其子类,常见的如: DisabledAccountException(禁用的帐号)、LockedAccountException(锁定的帐号)、UnknownAccountException(错误的帐号)、ExcessiveAttemptsException(登录失败次数过多)、IncorrectCredentialsException (错误的凭证)、ExpiredCredentialsException(过期的凭证)等,具体请查看其继承关系;对于页面的错误消息展示,最好使用如“用户名/密码错误”而不是“用户名错误”/“密码错误”,防止一些恶意用户非法扫描帐号库;
  6. 调用subject.hasRole方法判断是否是某一角色,调用subject.isPermitted方法判断是否具备某一行为。
  7. 最后可以调用subject.logout退出,其会自动委托给SecurityManager.logout方法退出。

基础原理和概念

Subject介绍

f79bc83d2a927b580fc07c4a7be1763a.png

Subject是Shiro的核心对象,基本所有身份验证、授权都是通过Subject完成。

相应的方法

1、身份信息获取

Object getPrincipal(); //Primary Principal  PrincipalCollection getPrincipals(); // PrincipalCollection

2、身份验证

void login(AuthenticationToken token) throws AuthenticationException; 

boolean isAuthenticated(); 

boolean isRemembere();

通过login登录,如果登录失败将抛出相应的AuthenticationException,如果登录成功调用isAuthenticated就会返回true,即已经通过身份验证;如果isRemembered返回true,表示是通过记住我功能登录的而不是调用login方法登录的。isAuthenticated/isRemembered是互斥的,即如果其中一个返回true,另一个返回false。

3、角色授权验证

boolean hasRole(String roleIdentifier);  
 boolean[] hasRoles(List<String> roleIdentifiers);  
 boolean hasAllRoles(Collection<String> roleIdentifiers);  
 void checkRole(String roleIdentifier) throws AuthorizationException;  
 void checkRoles(Collection<String> roleIdentifiers) throws AuthorizationException;  
 void checkRoles(String... roleIdentifiers) throws AuthorizationException;

hasRole进行角色验证,验证后返回true/false;而checkRole验证失败时抛出AuthorizationException异常。

4、权限授权验证

itted(String permission);  

boolean isPermitted(Permission permission);  

boolean[] isPermitted(String... permissions);  

boolean[] isPermitted(List<Permission> permissions);  

boolean isPermittedAll(String... permissions);  

boolean isPermittedAll(Collection<Permission> permissions);  

void checkPermission(String permission) throws AuthorizationException;  

void checkPermission(Permission permission) throws AuthorizationException;  

void checkPermissions(String... permissions) throws AuthorizationException;  

void checkPermissions(Collection<Permission> permissions) throws AuthoriationException;

isPermitted进行权限验证,验证后返回true/false;而checkPermission验证失败时抛出AuthorizationException。

5、会话

Session getSession(); //相当于getSession(true)  
Session getSession(boolean create);

类似于Web中的会话。如果登录成功就相当于建立了会话,接着可以使用getSession获取;如果create=false如果没有会话将返回null,而create=true如果没有会话会强制创建一个。

6、退出*

void logout();

ShiroFilter拦截器的工作原理

f3221d3dfc2cddd61622b6c092cfe009.png

filterChainDefinition的配置

•[urls] 部分的配置,其格式是:“url=拦截器[参数],拦截器[参数]”; •如果当前请求的url匹配[urls] 部分的某个url模式,将会执行其配置的拦截器。 •anon(anonymous)拦截器表示匿名访问(即不需要登录即可访问) •authc(authentication)拦截器表示需要身份认证通过后才能访问

其他的默认拦截器:

c4fa67f932296f2fe9c391c72e6c91a1.png

URL 匹配模式

•url模式使用Ant 风格模式 •Ant 路径通配符支持?、*,注意通配符匹配不包括目录分隔符“/”:

  • ?:匹配一个字符,如/admin? 将匹配/admin1,但不匹配/admin 或/admin/;
  • *:匹配零个或多个字符串,如/admin 将匹配/admin、/admin123,但不匹配/admin/1;
  • *:匹配路径中的零个或多个路径,如/admin/* 将匹配/admin/a 或/admin/a/b

URL 匹配顺序

•URL 权限采取第一次匹配优先的方式,即从头开始使用第一个匹配的url模式对应的拦截器链。 •如:

  • /bb/**=filter1
  • /bb/aa=filter2
  • /**=filter3

如果请求的url是“/bb/aa”,因为按照声明顺序进行匹配,那么将使用filter1 进行拦截。

认证流程

ea1f8521ba777fb27bb25474f27063bd.png

1、首先调用 Subject.login(token) 进行登录,其会自动委托给SecurityManager

2、SecurityManager 负责真正的身份验证逻辑;它会委托给Authenticator 进行身份验证;

3、Authenticator 才是真正的身份验证者,Shiro API 中核心的身份认证入口点,此处可以自定义插入自己的实现;

4、Authenticator 可能会委托给相应的 AuthenticationStrategy 进行多 Realm 身份验证,默认 ModularRealmAuthenticator 会调用AuthenticationStrategy 进行多 Realm 身份验证;

5、Authenticator 会把相应的 token 传入 Realm,从 Realm 获取身份验证信息,如果没有返回/抛出异常表示身份验证失败了。此处可以配置多个Realm,将按照相应的顺序及策略进行访问。

注意:Shiro本身不维护用户账户信息,需要程序员自己从数据库或别的地方获取数据提供给Shiro进行登录认证和权限认证。如何将数据提供给shiro呢?Shiro提供了抽象类供我们继承,通过实现抽象方法实现验证。我们称之为Realm。

什么是Realm

Realm:Shiro 从 Realm 获取安全数据(如用户、角色、权限),即 SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作。

如何自定义Realm

认证:

​ 继承AuthenticatingRealm 类。

​ 实现抽象方法doGetAuthenticationInfo方法

​ 在Spring容器中创建bean,在securityManager 安全管理器配置自定义的realm

授权:

​ 和认证的步骤差不多,只是继承的类不同,授权需要继承AuthorizingRealm 类,在AuthorizingRealm 类是AuthenticatingRealm的子类,而AuthorizingRealm 类没有实现doGetAuthenticationInfo方法,所以可以将认证和授权放在一个realm类中。

AuthorizingRealm(授权) 类和AuthenticatingRealm(认证)类的介绍

  1. AuthorizingRealm 类是AuthenticatingRealm的子类
  2. 两个抽象方法
  3. doGetAuthenticationInfo获取身份验证相关信息:首先根据传入的用户名获取User信息;然后如果user为空,那么抛出没找到帐号异常UnknownAccountException;如果user找到但锁定了抛出锁定异常LockedAccountException;最后生成AuthenticationInfo信息,交给间接父类AuthenticatingRealm使用CredentialsMatcher进行判断密码是否匹配,如果不匹配将抛出密码错误异常IncorrectCredentialsException;另外如果密码重试此处太多将抛出超出重试次数异常ExcessiveAttemptsException;在组装SimpleAuthenticationInfo信息时,需要传入:身份信息(用户名)、凭据(密文密码)、盐(username+salt),CredentialsMatcher使用盐加密传入的明文密码和此处的密文密码进行匹配。
  4. doGetAuthorizationInfo获取授权信息:PrincipalCollection是一个身份集合,因为我们现在就一个Realm,所以直接调用getPrimaryPrincipal得到之前传入的用户名即可;然后根据用户名调用UserService接口获取角色及权限信息。

认证方法的介绍

Shiro本身不维护用户账户信息,需要程序员自己从数据库或别的地方获取数据提供给Shiro进行登录认证和权限认证。

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException

参数为AuthenticationToken

570ae025b7cc54a4dd09fd16dd5cdde0.png

AuthenticationToken用于收集用户提交的身份(如用户名)及凭据(如密码)

public interface AuthenticationToken extends Serializable {  
        Object getPrincipal(); //身份  
        Object getCredentials(); //凭据  
    }

返回值类型为AuthenticationInfo

e51d9e9acb76bb3cd551cfa1cddadfc8.png

AuthenticationInfo有两个作用:

1、如果Realm是AuthenticatingRealm子类,则提供给AuthenticatingRealm内部使用的CredentialsMatcher进行凭据验证;(如果没有继承它需要在自己的Realm中自己实现验证);

2、提供给SecurityManager来创建Subject(提供身份信息)一般;

一般情况下返回其子类SimpleAuthenticationInfo。

授权流程

名词说明:

• 授权,也叫访问控制,即在应用中控制谁访问哪些资源(如访问页面/编辑数据/页面操作等)。在授权中需了解的几个关键对象:主体(Subject)、资源(Resource)、权限(Permission)、角色(Role)。

• 主体(Subject):访问应用的用户,在 Shiro 中使用 Subject 代表该用户。用户只有授权后才允许访问相应的资源。

• 资源(Resource):在应用中用户可以访问的 URL,比如访问 JSP 页面、查看/编辑某些数据、访问某个业务方法、打印文本等等都是资源。用户只要授权后才能访问。

• 权限(Permission):安全策略中的原子授权单位,通过权限我们可以表示在应用中用户有没有操作某个资源的权力。即权限表示在应用中用户能不能访问某个资源,如:访问用户列表页面查看/新增/修改/删除用户数据(即很多时候都是CRUD(增查改删)式权限控制)等。权限代表了用户有没有操作某个资源的权利,即反映在某个资源上的操作允不允许。

• Shiro 支持粗粒度权限(如用户模块的所有权限)和细粒度权限(操作某个用户的权限,即实例级别的)

• 角色(Role):权限的集合,一般情况下会赋予用户角色而不是权限,即这样用户可以拥有一组权限,赋予权限时比较方便。典型的如:项目经理、技术总监、CTO、开发工程师等都是角色,不同的角色拥有一组不同的权限。

da1b6827bf1de5f22bb0a681ba3a6f85.png

流程如下:

1、首先调用Subject.isPermitted/hasRole接口,其会委托给SecurityManager,而SecurityManager接着会委托给Authorizer;

2、Authorizer是真正的授权者,如果我们调用如isPermitted(“user:view”),其首先会通过PermissionResolver把字符串转换成相应的Permission实例;

3、在进行授权之前,其会调用相应的Realm获取Subject相应的角色/权限用于匹配传入的角色/权限;

4、Authorizer会判断Realm的角色/权限是否和传入的匹配,如果有多个Realm,会委托给ModularRealmAuthorizer进行循环判断,如果匹配如isPermitted/hasRole会返回true,否则返回false表示授权失败。

上面有说到授权需要自定义的Realm继承AuthorizingRealm类,并实现doGetAuthorizationInfo方法。

doGetAuthorizationInfo方法介绍

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals)

参数:PrincipalCollection

da10d2a863f4c161788e3313db5ec7c4.png

PrincipalCollection用于聚合这些身份信息

public interface PrincipalCollection extends Iterable, Serializable {  
        Object getPrimaryPrincipal(); //得到主要的身份  
        <T> T oneByType(Class<T> type); //根据身份类型获取第一个  
        <T> Collection<T> byType(Class<T> type); //根据身份类型获取一组  
        List asList(); //转换为List  
        Set asSet(); //转换为Set  
        Collection fromRealm(String realmName); //根据Realm名字获取  
        Set<String> getRealmNames(); //获取所有身份验证通过的Realm名字  
        boolean isEmpty(); //判断是否为空  
    }

返回值AuthorizationInfo

e97b690faa53dc3aa9b623cdf0cba2b9.png

AuthorizationInfo用于聚合授权信息的:

public interface AuthorizationInfo extends Serializable {  
    Collection<String> setRoles(); //获取角色字符串信息  
    Collection<String> getStringPermissions(); //获取权限字符串信息  
    Collection<Permission> getObjectPermissions(); //获取Permission对象信息  
}

一般情况下使用其子类SimpleAuthorizationInfo,设置Role和Permission并返回。

例如:

SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addRole(u.getRoles().getRolename());
for (Funs fun : u.getFuns()) {
    info.addStringPermission(fun.getFunurl());
}
return info;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值