基于springboot的shiro基本操作

Shiro执行逻辑

img

  • Application Code:编写的应用程序
  • 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的组织架构

img

由图看出,Security Manager是最复杂的系统

Security Manager内部

  • Authenticator:认证器,负责主体认证的,这是一个扩展点,如果用户觉得 Shiro 默认的不好,可以自定义实现;其需要认证策略(Authentication Strategy),即什么情况下算用户认证通过了;
  • Authorizer:授权器,或者访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中的哪些功能;
  • SessionManager:如果写过 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 提供了一些常见的加密组件用于如密码加密 / 解密的。

领域Realm的实现

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

Shiro身份验证

身份验证,即在应用中谁能证明他就是他本人。一般提供如他们的身份 ID 一些标识信息来表明他就是他本人,如提供身份证,用户名 / 密码来证明。

shiro中进行身份验证,需要提供principals(身份)和credentials(证明)

身份告诉shiro你是什么用户,证明用来证明你是这个身份。

最常见的principalscredentials就是用户名和密码了

principals = 用户名/邮箱/手机号等等

credentials = 密码/验证码/数字凭证等等

下面利用springboot环境来演示Shiro如何进行身份验证

演示

准备环境依赖

	<dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.2.2</version>
    </dependency>

准备用户身份

采用shiro.ini配置文件指定两个subject,一个用户名为wang,密码123,一个为zhang,密码123

[users]
wang = 123
zhang = 123

测试代码

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class DemoApplicationTests {

    @Test
    public void MainTest(){
//        初始化SecurityManager工厂,这里用ini文件作为realm
        IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
//        利用工厂产生一个SecurityManager实例
        SecurityManager securityManager = factory.getInstance();
//        将sm实例绑定到shiro提供的工具类中,下面的操作要利用此工具类
        SecurityUtils.setSecurityManager(securityManager);
//        获得主体,这里的主体是ini文件中的两个用户
        Subject subject = SecurityUtils.getSubject();
//        利用shiro提供的类创建一个虚拟用户用来登录
        UsernamePasswordToken token = new UsernamePasswordToken("wang", "123");

        try {
//		  对身份进行验证
            subject.login(token);
        } catch (AuthenticationException e) {
            System.out.println("用户名和密码错误,错误信息:"+e.getMessage());
        }
//        判断用户是否验证通过,通过返回true,不通过返回false
        boolean authenticated = subject.isAuthenticated();
         if(authenticated) System.out.println("登录成功");
        else System.out.println("登录失败");
//        退出登录
        subject.logout();
    }
}

对29行错误信息的解释

如果身份验证失败请捕获 AuthenticationException 或其子类,常见的如: DisabledAccountException(禁用的帐号)、LockedAccountException(锁定的帐号)、UnknownAccountException(错误的帐号)、ExcessiveAttemptsException(登录失败次数过多)、IncorrectCredentialsException (错误的凭证)、ExpiredCredentialsException(过期的凭证)等,具体请查看其继承关系;对于页面的错误消息展示,最好使用如 “用户名 / 密码错误” 而不是 “用户名错误”/“密码错误”,防止一些恶意用户非法扫描帐号库;

从如上代码可总结出身份验证的步骤

  1. 收集用户身份 / 凭证,即如用户名 / 密码;
  2. 调用 Subject.login 进行登录,如果失败将得到相应的 AuthenticationException 异常,根据异常提示用户错误信息;否则登录成功;
  3. 最后调用 Subject.logout 进行退出操作。

如上测试的几个问题:

  1. 用户名 / 密码硬编码在 ini 配置文件,以后需要改成如数据库存储,且密码需要加密存储;
  2. 用户身份 Token 可能不仅仅是用户名 / 密码,也可能还有其他的,如登录时允许用户名 / 邮箱 / 手机号同时登录。

从代码可以看出这些操作好像是subject完成的,但实际上,全部是subject委托给securityManager完成的,而SecurityManager对于身份验证的操作,会交给自己的子模块Authenticator完成,Authenticator将获取到的token(用户信息及凭证)交给realm,realm如果没有抛出异常,那么身份就验证成功了。

可以看出,Realm是验证身份的最终站,因此,我们可以配置多个Realm来多次验证Authenticator交过来的token

Realm配置

Realm是安全数据源,我们刚刚的演示中使用了ini文件作为数据源,那么我们使用的Realm在shiro中就是

org.apache.shiro.realm.text.IniRealm

shiro中定义了Realm接口,他是所有Realm的父类接口,代码如下

String getName(); //返回一个唯一的Realm名字
boolean supports(AuthenticationToken token); //判断此Realm是否支持此Token
AuthenticationInfo getAuthenticationInfo(AuthenticationToken token)
 throws AuthenticationException;  //根据Token获取认证信息

我们可以自定义Realm,然后通过ini配置文件指定securityManager的Realm实现,这样便可实现多Realm验证

创建一个shiro-multi-realm.ini文件,假设现在我们自定义了两个Realm

那么可以通过下面的配置文件进行多Realm配置

\#声明一个realm
myRealm1 = com.whr.realm.MyRealm1
myRealm2 = com.whr.realm.MyRealm2
\#$符号表示引用上面已经定义好的对象
\#指定securityManager的realms实现,这一行可删除,删除后将按照上面声明的顺序加载
securityManager.realms=$myRealm1,$myRealm2

securityManager 会按照 realms 指定的顺序进行身份认证。此处我们使用显示指定顺序的方式指定了 Realm 的顺序,如果删除 “securityManager.realms=$myRealm1,$myRealm2”,那么securityManager 会按照 realm 声明的顺序进行使用(即无需设置 realms 属性,其会自动发现),当我们显示指定 realm 后,其他没有指定 realm 将被忽略,如 “securityManager.realms=$myRealm1”,那么 myRealm2 不会被自动设置进去。

Shiro提供的Realm

img

以后一般继承 AuthorizingRealm(授权)即可;其继承了 AuthenticatingRealm(即身份验证),而且也间接继承了 CachingRealm(带有缓存实现)。

Shiro授权

为什么需要授权,因为在页面中,有些资源我们不想让没有权限的人看到,例如在一个后台管理系统登录窗口页面,我们会有几个角色,例如:管理员(admin),用户(user)等等,那么管理员和用户能看到的页面和进行的操作一定是不同的。这时我们就需要对不同的角色进行授权。

在授权中需了解的几个关键对象:

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

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

  • 权限(Permission) 安全策略中的原子授权单位,通过权限我们可以表示在应用中用户有没有操作某个资源的权力。即权限表示在应用中用户能不能访问某个资源,如: 访问用户列表页面 查看/新增/修改/删除用户数据(即很多时候都是 CRUD(增查改删)式权限控制)打印文档等。如上可以看出,权限代表了用户有没有操作某个资源的权利,即反映在某个资源上的操作允不允许,不反映谁去执行这个操作。所以后续还需要把权限赋予给用户,即定义哪个用户允许在某个资源上做什么操作(权限),Shiro 不会去做这件事情,而是由实现人员提供。

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

授权方式

Shiro 支持三种方式的授权:

编程式:通过写 if/else 授权代码块完成:

Subject subject = SecurityUtils.getSubject();
if(subject.hasRole(“admin”)) {
    //有权限
} else {
    //无权限
}

注解式:通过在执行的 Java 方法上放置相应的注解完成:

@RequiresRoles("admin")
public void hello() {
    //有权限
}

没有权限将抛出相应的异常;

JSP/GSP 标签:在 JSP/GSP 页面通过相应的标签完成:

<shiro:hasRole name="admin">
<!— 有权限 —>
</shiro:hasRole>

演示

基于角色的演示控制

[users]
wang = 123 ,admin,user
zhang = 123 ,user

给wang用户设置了两个角色,admin和user,zhang用户只有user角色

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class DemoApplicationTests {

    /*
    * 利用静态代码块完成securityManager的注册,但是大多数情况下是不用这样做的,这里仅作测试
    * */
    static {
        SecurityManager securityManager = new IniSecurityManagerFactory("classpath:shiro.ini").
                getInstance();
        SecurityUtils.setSecurityManager(securityManager);
    }
    
    @Test
    public void MainTest(){
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken zhang = new UsernamePasswordToken("zhang", "123");
        subject.login(zhang);
        if(subject.hasRole("admin")){
            System.out.println("have permission");
        }else{
            System.out.println("don't have permission");
        }
//        退出登录
        subject.logout();
    }


}

上述示例只演示了测试此用户是否拥有某一角色,下面给此角色赋予权限

[users]
zhang=123,admin,user
wang=123,user
[roles]
admin = admin:create,admin:delete,admin:update
user = user:read
@Test
    public void MainTest(){
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken zhang = new UsernamePasswordToken("zhang", "123");
        subject.login(zhang);
        if(subject.hasRole("user")){
            System.out.println("have role");
//            判断此用户是否拥有删除权限,没有则报错
            try{
                subject.checkPermission("admin:delete");
            }catch(UnauthorizedException e){
                System.out.println(e.getMessage());
            }
        }else{
            System.out.println("don't have role");
        }
//        退出登录
        subject.logout();
    }
//报错信息
Subject does not have permission [admin:delete]

Springboot集成Shiro

开始之前,所有页面结构

在这里插入图片描述

在pom.xml中添加如下三个依赖

		<!--shiro核心包-->
		<dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.2.2</version>
        </dependency>
		<!--shiro与spring整合的jar包-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.7.1</version>
        </dependency>
		<!--thymeleaf依赖包-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

在yml文件中进行配置

spring:
  thymeleaf:
    #配置模板路径,默认是templates,可以不用配置
    prefix: classpath:/templates/
    suffix: .html
    cache: false #关闭页面缓存

自定义一个MyShiroConfig

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author
 * @description
 */
@Configuration
public class MyShiroConfig {
//        利用securityManager对象来注册shiroFilter
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean getShiroFilterFactoryBean
            (@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
//        关联SecurityManager
        shiroFilter.setSecurityManager(defaultWebSecurityManager);
        return shiroFilter;
    }
//        注册SecurityManager对象,其中底层的realm用自己的实现
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//        关联realm
        securityManager.setRealm(userRealm);
        return securityManager;
    }

//		  注册realm,这个realm是自定义的
    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    }
}

自定义一个Realm

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

/**
 * @author
 * @description
 */
public class UserRealm extends AuthorizingRealm {

//    给用户授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行doGetAuthorizationInfo-PrincipalCollection");
        return null;
    }

//    认证用户的token
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行doGetAuthorizationInfo-AuthenticationToken");
        return null;
    }
}

上面的代码自定义了UserRealm,这个说明了SecurityManager需要realm时的访问对象,然后定义了一个过滤器,这个过滤器可以拦截用户的请求并进行页面的跳转

在前端控制器中拿到前端发来的数据后,封装成token,交付给SecurityManager对象,sm再去Realm中去验证用户的身份及权限。

例如,我们拥有下面的一个Controller控制器

 @RequestMapping("/userLogin")
    public String login(String username, String password, Model model){
//        获取当前登录的用户
        Subject subject = SecurityUtils.getSubject();
//        封装用户的登录数据
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try{
//            这里的login将会把token交付给securityManager,sm再去UserRealm中认证用户
            subject.login(token);
//            登录成功跳转
            return "index";
        }catch (UnknownAccountException e){
            //用户名不存在
            model.addAttribute("msg","用户名不存在");
            return "login";
        }catch (IncorrectCredentialsException e){
            //密码不正确
            model.addAttribute("msg","密码错误");
            return "login";
        }
    }

当用户发起/userLogin请求时,前端将用户名和密码封装成一个token,同时调用subject的login方法,会将token交给SM对象,SM对象再访问UserRealm中去验证用户身份

拦截用户请求

如果想要拦截用户请求,那么需要在MyShiroConfig类中修改shiroFilter进行配置

@Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean getShiroFilterFactoryBean
            (@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(defaultWebSecurityManager);
//      添加shiro的内置过滤器,对请求进行拦截
        /*
            anno:无需认证即可访问 默认的
            authc:必须认证才可以访问
            user:必须记住我才能访问
            perms:拥有对某个资源的权限才能访问
            role: 拥有某个角色的权限才能访问
         */
        Map<String, String> filterMap = new LinkedHashMap<>();
/*       
        配置后,shiro将会对用户发来的这两个请求进行拦截并认证
        filterMap.put("/user/add","authc");
       filterMap.put("/user/delete","authc");
 */
        filterMap.put("/user/*","authc");
        shiroFilter.setFilterChainDefinitionMap(filterMap);
//        如果没有权限就跳转到login页面
        shiroFilter.setLoginUrl("/login");
        return shiroFilter;
    }

此时用户想要访问这两个请求时,会跳转到login页面,而login页面将会发起/userLogin请求

认证用户

在UserRealm中的第二个重载方法中这样写

//    认证用户的交付过来的token
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行doGetAuthorizationInfo-AuthenticationToken");
//        假定的用户名和密码。实际开发中去数据库中取
        String username = "root";
        String password = "123456";
//        由于传入的是UsernamePasswordToken,这里需要向下转型
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        if (!token.getUsername().equals(username)) {
//            如果用户名和假定用户名不匹配,返回null,抛出一个UnKnownAccountException异常
            return null;
        }
//        用户名的判断我们自己做,而密码的判断需要交给shiro做,并且判断时shiro会自动调取token中的password
        return new SimpleAuthenticationInfo("",password,"");
    }

密码加密

密码加密前需要将数据库或假定的密码测试出来结果

shiro共有两种加密方式

  • SimpleCredentialsMatcher(简单证明匹配): SimpleCredentialsMatcher对存储的用户凭证和从AuthenticationToken提交的用户凭证直接执行相等的检查。

  • HashedCredentialsMatcher:取代将凭证按它们原始形式存储并执行原始数据的对比,存储终端用户的凭证(如密码)更安全的办法是在存储数据之前,先进行hash运算。

shiro的加密算法

import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class DemoApplicationTests {


    @Test
    public void MainTest(){
        Md5Hash md5Hash = new Md5Hash("123456");
        System.out.println("md5Hash.getAlgorithmName()="+md5Hash.getAlgorithmName());//默认为MD5
        System.out.println("md5Hash.getSalt()="+md5Hash.getSalt()); //默认为null
        System.out.println("md5Hash.getIterations()="+md5Hash.getIterations());//默认为1
//        不加盐,散列次数为1的加密结果
        System.out.println(md5Hash);
//        加盐,盐值一般为用户名,散列次数为1的加密结果
        md5Hash = new Md5Hash("123456","root");
        System.out.println(md5Hash);
//        一般开发种,加盐,并且加密次数为3次
        md5Hash = new Md5Hash("123456","root",3);
        System.out.println(md5Hash);

        //4.利用SimpleHash来设置md5(上面三种都可以通过这个来设置,这里举例加盐加散列次数的)
        //第一个参数是算法名称,这里指定md5,第二个是要加密的密码,第三个参数是加盐,第四个是散列次数
        SimpleHash hash = new SimpleHash("md5", "123456", "root",3);
        System.out.println(hash.toString());
    }


}

授权

MyShiroConfig中配置过滤器要授权的请求地址

 @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean getShiroFilterFactoryBean
            (@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(defaultWebSecurityManager);
//      添加shiro的内置过滤器,对请求进行拦截
        /*
            anno:无需认证即可访问 默认的
            authc:必须认证才可以访问
            user:必须记住我才能访问
            perms:拥有对某个资源的权限才能访问
            role: 拥有某个角色的权限才能访问
         */
        Map<String, String> filterMap = new LinkedHashMap<>();
/*
        配置后,shiro将会对用户发来的这两个请求进行拦截并认证
        filterMap.put("/user/add","authc");
        filterMap.put("/user/delete","authc");
 */
//        配置权限,配置权限一定要在认证前才能生效
        filterMap.put("/user/add","perms[user:add]");
//        给delete请求设置只有拥有权限才能访问,此时会跳转到realm中
        filterMap.put("/user/delete","perms[user:delete]");
        filterMap.put("/user/*","authc");

        shiroFilter.setFilterChainDefinitionMap(filterMap);
//        如果没有权限就跳转到login页面
        shiroFilter.setLoginUrl("/login");
//        如果没有授权就跳转到未授权页面
        shiroFilter.setUnauthorizedUrl("/unauth");
        return shiroFilter;
    }

修改UserRealm如下

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;

/**
 * @author
 * @description
 */
public class UserRealm extends AuthorizingRealm {

//    给用户授权,每次过滤器拦截到perms[user:add]都会跳转到此进行授权认证
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行doGetAuthorizationInfo-PrincipalCollection");
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

//        如果此用户有角色,只需要addRole即可
//        simpleAuthorizationInfo.addRole("role");
        Subject subject = SecurityUtils.getSubject();
//        通过下面这两个方法都可以拿到认证用户方法传来的perms
        String perms = (String) subject.getPrincipal();
//        String perms = principalCollection.getPrimaryPrincipal();
//        将此权限赋予给此用户
        simpleAuthorizationInfo.addStringPermission(perms);
        return simpleAuthorizationInfo;
    }

//    认证用户的交付过来的token
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行doGetAuthorizationInfo-AuthenticationToken");
//        假定的用户名和密码。实际开发中去数据库中取
        String username = "root";
        String password = "123456";
//        假定用户只有add权限没有delete权限
        String perms = "user:add";
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        if (!token.getUsername().equals(username)) {
            return null;
        }
//        将用户的权限perms通过此返回值传输到doGetAuthorizationInfo方法中,实际开发中传输对象
        return new SimpleAuthenticationInfo(perms,password,"");
    }
}

到此springboot的基本操作就演示完毕了,在jsp的页面中,shiro可以利用标签进行一些测试,在thymeleaf中也可以利用标签,只不过需要加载新的jar包,是thymeleaf和shiro整合的jar包,具体的我没有研究,具体用到再说。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值