Shiro安全框架学习

一、shiro简介(简介内容来自百度百科)

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

三个核心组件:Subject, SecurityManager 和 Realms.
Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。
Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。
从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。
Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。如果系统默认的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现。

二、学习目标

① 认识shiro的整体架构,各组件的概念

② shiro认证,授权的过程

③ shiro自定义的realm、Filter

④ shiro的加密

想更了解“shiro”的小伙伴可以去慕课网搜索“shiro安全框架入门”
链接地址:https://www.imooc.com/view/977
在这里插入图片描述

三、shiro与spring Security的比较(spring的官网也是用shiro做安全管理的)

1、Shiro比Spring更容易使用,实现和最重要的理解。

2、Spring Security更加知名的唯一原因是因为品牌名称。

3、“Spring”以简单而闻名,但讽刺的是很多人发现安装Spring Security很难
但是Spring Security却有更好的社区支持。

4、Apache Shiro在Spring Security处理密码学方面有一个额外的模块。

5、Spring-security 对spring 结合较好,如果项目用的springmvc ,使用起来很方便。但是如果项目中没有用到spring,那就不要考虑它了。

6、Shiro 功能强大、且 简单、灵活。是Apache 下的项目比较可靠,且不跟任何的框架或者容器绑定,可以独立运行。
总结
Apache shiro: 简单灵活、可脱离spring、粒度较粗
spring Security: 复杂笨重、不可脱离spring、粒度更细

四、Shiro的整体架构

在这里插入图片描述
①上面标记为1的是shiro的主体部分subject,可以理解为当前的操作用户

② Security Manager为Shiro的核心,shiro是通过security Manager来提供安全服务的,security Manager管理着Session Manager、Cache Manager等其他组件的实例:Authenticator(认证器,管理我们的登录登出) Authorizer(授权器,负责赋予主体subject有哪些权限) Session Manager(shiro自己实现的一套session管理机制,可以不借助任何web容器的情况下使用session) Session Dao(提供了session的增删改查操作) cache Manager(缓存管理器,用于缓存角色数据和权限数据) Pluggable Realms(shiro与数据库/数据源之间的桥梁,shiro获取认证信息、权限数据、角色数据都是通过Realms来获取)

③ 上图标记为2的cryptography是用来做加密的,使用它可以非常方便快捷的进行数据加密。

④ 上面箭头的流程可以这样理解:主体提交请求到Security Manager,然后由Security Manager调用Authenticator去做认证,而Authenticator去获取认证数据的时候是通过Realms从数据源中来获取的,然后把从数据源中拿到的认证信息与主体提交过来的认证信息做比对。授权器Authorizer也是一样。

五、Shiro的认证

① 创建Security Manager:Security Manager是用来提供安全服务的,所以在做shiro认证的时候要先创建此对象

② 主体Subject提交请求给Security Manager

③ Security Manager调用Authenticator组件做认证

④Authenticator通过Realm来从数据源中获取认证数据

1、引入依赖

<dependencies>
	<dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.4.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>RELEASE</version>
	</dependency>
</dependencies>

2、测试用例

package com.shiroDemo;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.SimpleAccountRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Before;
import org.junit.Test;

/**
 * @program: shiro-demo
 * @description: shiro权限测试类
 * @author: Mr.Wang
 * @create: 2021-11-05 09:42
 **/
public class AuthenticationTest {

    //除了SimpleAccountRealm还有JdbcRealm等
    SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();

    //在认证之前先在Realm中添加一个用户,创建Security Manager的时候要用到Realm
    @Before
    public void addUser(){
        simpleAccountRealm.addAccount("wxc","123456");
    }

    @Test//Shiro的认证
    public void testAutentication(){
        //1.构建Security Manager环境(Security Manager是用来提供安全服务的,所以在做shiro认证的时候要先创建此对象,创建Security Manager对象之后要设置Realm)
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(simpleAccountRealm);

        //2.获取向Security Manager提交请求的subject,而主体subject可以通过shiro提供的一个工具类SecurityUtils来获取
        //使用SecurityUtils之前要设置Security Manager环境
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject = SecurityUtils.getSubject();

        //3.主体Subject提交请求给Security Manager -->  subject.login(token);
        //提交请求时需要一个token,所以要先创建token
        UsernamePasswordToken token = new UsernamePasswordToken("wxc","123456");
        subject.login(token);

        //4. shiro提供了一个检查主体subject是否认证的方法isAuthenticated(),此方法的返回结果是一个boolean值
        System.out.println(subject.isAuthenticated());
		
		//5.注销
        subject.logout();
        System.out.println(subject.isAuthenticated());
        
    }
}

执行结果:
在这里插入图片描述

六、Shiro的授权

① 创建Security Manager

② 主体subject授权

③ 主体授权是交给Security Manager授权

④ Security Manager调用授权器Authorizer授权

⑤ 通过Realm在数据库或者缓存中来获取授权的数据(角色数据和权限数据)

package com.shiroDemo;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.SimpleAccountRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Before;
import org.junit.Test;

/**
 * @program: shiro-demo
 * @description: shiro权限测试类
 * @author: Mr.Wang
 * @create: 2021-11-05 09:42
 **/
public class AuthenticationTest {

    //除了SimpleAccountRealm还有JdbcRealm等
    SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();

    //在认证之前先在Realm中添加一个用户,创建Security Manager的时候要用到Realm
    @Before
    public void addUser(){
        //shiro的授权 user,user1都是角色,这里可以自定义多个角色
        simpleAccountRealm.addAccount("wxc","123456","admin","user","user1");
    }

    @Test//Shiro的授权
    public void test3(){
        //1.构建Security Manager环境(Security Manager是用来提供安全服务的,所以在做shiro认证的时候要先创建此对象,创建Security Manager对象之后要设置Realm)
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(simpleAccountRealm);
        //2.获取向Security Manager提交请求的subject,而主体subject可以通过shiro提供的一个工具类SecurityUtils来获取
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject = SecurityUtils.getSubject();
        //3.主体Subject提交请求给Security Manager -->  subject.login(token);
        UsernamePasswordToken token = new UsernamePasswordToken("wxc","123456");
        subject.login(token);
        //4. shiro提供了一个检查主体subject是否认证的方法isAuthenticated(),此方法的返回结果是一个boolean值
        System.out.println(subject.isAuthenticated());
        //校验角色
        subject.checkRoles("user1");
    }

}

执行结果:
在这里插入图片描述

七、Shiro常用的Realm

**1、**内置Realm,“IniRealm"在项目中新建一个ini文件,下面的内容的意思是,新建了一个用户,账号是xiehuaxin,密码为123456,此账号的角色为admin,而admin角色又具有删除用户和更新用户的权限(多个权限中间用逗号分隔),注意这里的“user:delete”不是一定要这样写的,只是一个字符串,你也可以写成"admin=shanchuyonghu”,这要在校验的时候也用“shanchuyonghu”来匹配就行了,当然这种命名习惯还是不建议的,建议使用“user:delete”这种对象+动作的命名方式。
在这里插入图片描述
shiro.ini文件文字可自定义,路径也可以放在自己喜欢的路径下,这里做测试我放在resources下。
文件内容:
在这里插入图片描述

package com.shiroDemo;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Test;


/**
 * @program: shiro-demo
 * @description: Shiro内置Realm
 * @author: Mr.Wang
 * @create: 2021-11-05 10:46
 **/
public class IniRealmTest {

    @Test
    public void test(){
    	//这里设置.ini文件的路径
        IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
        //1.构建Security Manager环境(Security Manager是用来提供安全服务的,所以在做shiro认证的时候要先创建此对象,创建Security Manager对象之后要设置Realm)
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(iniRealm);
        //2.获取向Security Manager提交请求的subject,而主体subject可以通过shiro提供的一个工具类SecurityUtils来获取 SecurityUtils.setSecurityManager(defaultSecurityManager);//使用SecurityUtils之前要设置Security Manager环境 Subject subject = SecurityUtils.getSubject(); //3.主体Subject提交请求给Security Manager --> subject.login(token); UsernamePasswordToken token = new UsernamePasswordToken("xiehuaxin","123456");//提交请求时需要一个token,所以要先创建token subject.login(token); //4. shiro提供了一个检查主体subject是否认证的方法isAuthenticated(),此方法的返回结果是一个boolean值 System.out.println(subject.isAuthenticated());
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject = SecurityUtils.getSubject();
        //3.生产token
        UsernamePasswordToken token = new UsernamePasswordToken("root","123456");
        //4.登录
        subject.login(token);
        //判断是否登录认证
        System.out.println(subject.isAuthenticated());
        //5.校验角色
        subject.checkRoles("user");
        //6.校验权限
        subject.checkPermission("user:add");
    }

}

执行结果:
在这里插入图片描述
2、JdbcRealm
1、引入数据库依赖

	<!-- 引入驱动包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.45</version>
        </dependency>
        <!--引入数据源-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.4</version>
        </dependency>

2、创建数据库及相关表(Mysql)



SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for role_permission
-- ----------------------------
DROP TABLE IF EXISTS `role_permission`;
CREATE TABLE `role_permission`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `role_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `permission` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of role_permission
-- ----------------------------
INSERT INTO `role_permission` VALUES (1, 'admin', 'admin:add');
INSERT INTO `role_permission` VALUES (2, 'admin', 'admin:delete');
INSERT INTO `role_permission` VALUES (3, 'user', 'user:add');
INSERT INTO `role_permission` VALUES (4, 'user', 'user:delete');

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'wxc', '123456');

-- ----------------------------
-- Table structure for user_roles
-- ----------------------------
DROP TABLE IF EXISTS `user_roles`;
CREATE TABLE `user_roles`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `role_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user_roles
-- ----------------------------
INSERT INTO `user_roles` VALUES (1, 'wxc', 'admin');
INSERT INTO `user_roles` VALUES (2, 'wxc', 'user');

SET FOREIGN_KEY_CHECKS = 1;

测试:

package com.shiroDemo;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Test;

/**
 * @program: shiro-demo
 * @description: JdbcRealm测试
 * @author: Mr.Wang
 * @create: 2021-11-05 11:27
 **/
public class JdbcRealmTest {

    DruidDataSource dataSource = new DruidDataSource();

    {//设置数据源
        dataSource.setUrl("jdbc:mysql:///test?useSSL=false");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
    }

    @Test
    public void test(){
        //1.创建jdbcReaml对象
        JdbcRealm jdbcRealm = new JdbcRealm();

        //2.设置数据源
        jdbcRealm.setDataSource(dataSource);

        //这里需要注意的是,在使用JdbcRealm的时候要设置权限的开关,只有设置为true时才会去查询权限数据
        jdbcRealm.setPermissionsLookupEnabled(true);

        //设置认证查询
        String sql = "select password from user where username = ?";
        jdbcRealm.setAuthenticationQuery(sql);

        //设置角色查询
        String roleSql = "select role_name from user_roles where username = ?";
        jdbcRealm.setUserRolesQuery(roleSql);

        //设置权限查询
        String perSql = "select permission from role_permission where role_name = ?";
        jdbcRealm.setPermissionsQuery(perSql);

        //构建Security Manager环境(Security Manager是用来提供安全服务的,所以在做shiro认证的时候要先创建此对象,创建Security Manager对象之后要设置Realm)
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(jdbcRealm);

        //获取向Security Manager提交请求的subject,而主体subject可以通过shiro提供的一个工具类SecurityUtils来获取
        SecurityUtils.setSecurityManager(defaultSecurityManager);//使用SecurityUtils之前要设置Security Manager环境
        Subject subject = SecurityUtils.getSubject();

        //主体Subject提交请求给Security Manager --> subject.login(token);
        UsernamePasswordToken token = new UsernamePasswordToken("wxc","123456");//提交请求时需要一个token,所以要先创建token
        subject.login(token);
        
        //shiro提供了一个检查主体subject是否认证的方法isAuthenticated(),此方法的返回结果是一个boolean值
        System.out.println(subject.isAuthenticated());
        subject.checkRoles("admin","user");
    }


}

执行结果:
在这里插入图片描述

在使用JdbcRealm时,如果没有设置查询语句,JdbcReal有自己默认的查询语句。

八、自定义Realm

通过查看JdbcRealm或者IniRealm的源码可以发现,它们都继承自AuthorizingRealm,所以要自定义Realm也要使自定义的Realm继承AuthorizingRealm.

package com.shiroDemo;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @program: shiro-demo
 * @description: 自定义Realm
 * @author: Mr.Wang
 * @create: 2021-11-08 10:25
 **/
public class CustomRealm extends AuthorizingRealm {

    Map<String,String> userMap = new HashMap<String, String>();
    {
        userMap.put("wxc","123456");
        super.setName("customRealm");//自定义
    }

    /**
     * 用来做授权(就是checkRole,checkPermission时用到的)
     * @param principals
     * @return
     */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("自定义授权方法");
        //1、现获取用户名
        String userName = (String)principals.getPrimaryPrincipal();

        //2、从数据库或者缓存中获取角色授权
        Set<String> roleSet = getRolesByUserName(userName);

        //3、从数据库或者缓存中获取权限数据
        Set<String> perSet = getPermissionsByUserName(userName);
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.setStringPermissions(perSet);
        simpleAuthorizationInfo.setRoles(roleSet);
        return simpleAuthorizationInfo;
    }

    /**
     * 从数据库或缓存中获取权限数据(这里模拟数据库查询)
     * @param userName
     * @return
     */
    private Set<String> getPermissionsByUserName(String userName) {
        Set<String> perSet = new HashSet<String>();
        perSet.add("user:add");
        perSet.add("user:delete");
        return perSet;
    }

    /**
     * 通过用户名获取到角色数据(这里为了简单点就不真的去查询数据库了,仅模拟数据库查询)
     * @param userName
     * @return
     */
    private Set<String> getRolesByUserName(String userName) {
        Set<String> roleSet = new HashSet<String>();
        roleSet.add("admin");
        roleSet.add("user");
        return roleSet;
    }

    /**
     * 用来做认证(就是login时用到的)
     * @param token           主体subject传过来的验证信息
     * @return
     * @throws AuthenticationException
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("自定义认证方法");
        //1.先通过主体传过来的验证信息获取用户名
        String userName = (String)token.getPrincipal();

        //2.通过用户名去数据库中获取凭证
        String password = getPasswordByUserName(userName);
        if(password == null){
            return null;
        }

        //查询到用户,则返回AuthenticationInfo对象
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userName,password,"customRealm");
        return simpleAuthenticationInfo;
    }

    /**
     * 通过userName查询对应用户密码(这里直接通过Map获取)
     * @param userName
     * @return
     */
    private String getPasswordByUserName(String userName) {
        return userMap.get(userName);
    }
}

测试自定义Realm

package com.shiroDemo;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.junit.Test;

/**
 * @program: shiro-demo
 * @description: 测试自定义Realm
 * @author: Mr.Wang
 * @create: 2021-11-08 10:57
 **/
public class CustomRealmTest {

    @Test
    public void test1(){//自定义Realm测试
        CustomRealm customRealm = new CustomRealm();
        //1.构建Security Manager环境(Security Manager是用来提供安全服务的,所以在做shiro认证的时候要先创建此对象,创建Security Manager对象之后要设置Realm)
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(customRealm);

        //2.获取向Security Manager提交请求的subject,而主体subject可以通过shiro提供的一个工具类SecurityUtils来获取
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject = SecurityUtils.getSubject();

        //3.主体Subject提交请求给Security Manager -->  subject.login(token);
        UsernamePasswordToken token = new UsernamePasswordToken("wxc","123456");
        subject.login(token);

        //4. shiro提供了一个检查主体subject是否认证的方法isAuthenticated(),此方法的返回结果是一个boolean值
        System.out.println(subject.isAuthenticated());
        subject.checkRoles("admin");
        subject.checkPermission("user:delete");
    }
    
 }

执行结果:
在这里插入图片描述

九、Shiro的加密

1、md5加密

package com.shiroDemo;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.junit.Test;

/**
 * @program: shiro-demo
 * @description: 测试自定义Realm
 * @author: Mr.Wang
 * @create: 2021-11-08 10:57
 **/
public class CustomRealmTest {

    @Test
    public void test2(){//shiro加密测试
        CustomRealm customRealm = new CustomRealm();

        //1.构建Security Manager环境(Security Manager是用来提供安全服务的,所以在做shiro认证的时候要先创建此对象,创建Security Manager对象之后要设置Realm)
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(customRealm);

        //md5加密测试
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("md5");//设置加密算法名称
        matcher.setHashIterations(1);//设置加密次数
        customRealm.setCredentialsMatcher(matcher);

        //2.获取向Security Manager提交请求的subject,而主体subject可以通过shiro提供的一个工具类SecurityUtils来获取
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject = SecurityUtils.getSubject();

        //3.主体Subject提交请求给Security Manager -->  subject.login(token);
        UsernamePasswordToken token = new UsernamePasswordToken("wxc","123456");
        subject.login(token);

        //4. shiro提供了一个检查主体subject是否认证的方法isAuthenticated(),此方法的返回结果是一个boolean值
        System.out.println(subject.isAuthenticated());
        subject.checkRoles("admin");
        subject.checkPermission("user:delete");
    }

    @Test
    public void test3(){//因为正常情况,我们设置了加密,数据也是被加密过的,前面自定义的map数据是没有加密的这路输入密码获取加密后的密码去替换map的数据
        Md5Hash md5Hash = new Md5Hash("123456");
        System.out.println(md5Hash.toString());
    }

}

因为正常情况,我们设置了加密,数据也是被加密过的,前面自定义的map数据是没有加密的这里输入密码获取加密后的密码去替换map的数据
在这里插入图片描述
在这里插入图片描述
替换后执行测试代码:

@Test
    public void test2(){//shiro加密测试
        CustomRealm customRealm = new CustomRealm();

        //1.构建Security Manager环境(Security Manager是用来提供安全服务的,所以在做shiro认证的时候要先创建此对象,创建Security Manager对象之后要设置Realm)
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(customRealm);

        //md5加密测试
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("md5");//设置加密算法名称
        matcher.setHashIterations(1);//设置加密次数
        customRealm.setCredentialsMatcher(matcher);

        //2.获取向Security Manager提交请求的subject,而主体subject可以通过shiro提供的一个工具类SecurityUtils来获取
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject = SecurityUtils.getSubject();

        //3.主体Subject提交请求给Security Manager -->  subject.login(token);
        UsernamePasswordToken token = new UsernamePasswordToken("wxc","123456");
        subject.login(token);

        //4. shiro提供了一个检查主体subject是否认证的方法isAuthenticated(),此方法的返回结果是一个boolean值
        System.out.println(subject.isAuthenticated());
        subject.checkRoles("admin");
        subject.checkPermission("user:delete");
    }

执行结果:
在这里插入图片描述

2、盐值加密
盐值加密和md5加密很相似:
先获取盐值加密后的密码,这里"123"表示盐值是我随便写的,在实际项目中可以使用对象的id(userid)来做盐值进行生成

 @Test
    public void test3(){
      	Md5Hash md5Hash = new Md5Hash("123456","123");
        System.out.println(md5Hash.toString());
    }

执行后复制加密后的密码替换map集合的密码:
在这里插入图片描述
替换之后,在我们自定义Realm中添加一句代码:
simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(“123”));
123是盐值

/**
     * 用来做认证(就是login时用到的)
     * @param token           主体subject传过来的验证信息
     * @return
     * @throws AuthenticationException
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("自定义认证方法");
        //1.先通过主体传过来的验证信息获取用户名
        String userName = (String)token.getPrincipal();

        //2.通过用户名去数据库中获取凭证
        String password = getPasswordByUserName(userName);
        if(password == null){
            return null;
        }

        //查询到用户,则返回AuthenticationInfo对象
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userName,password,"customRealm");
        simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("123"));
        return simpleAuthenticationInfo;
    }

执行结果:
在这里插入图片描述
shiro的基础内容大致学习完毕,如想学习更深层的知识点可以看些shiro底层视频讲解!谢谢观看

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇

)">
下一篇>>