shiro实战案例

结构

在这里插入图片描述
在这里插入图片描述

概念介绍
  • Subject

    我们把用户或者程序称为主体(如用户,第三方服务,cron作业),主体去访问系统或者资源
    SecurityManager

    安全管理器,Subject的认证和授权都要在安全管理器下进行

  • Authenticator

    认证器,主要负责Subject的认证
    Realm

    数据域,Shiro和安全数据的连接器,好比jdbc连接数据库; 通过realm获取认证授权相关信息

  • Authorizer

    授权器,主要负责Subject的授权, 控制subject拥有的角色或者权限

  • Cryptography

加解密,Shiro的包含易于使用和理解的数据加解密方法,简化了很多复杂的api

  • Cache Manager

缓存管理器,比如认证或授权信息,通过缓存进行管理,提高性能

代码
  • 常用api


在这里插入图片描述
在这里插入图片描述

-项目结构
在这里插入图片描述

  • 配置 pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.0.0-M1</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>shiro_demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>shiro_demo</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>17</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
<!--			<scope>runtime</scope>-->
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.6</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>1.4.0</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
	<repositories>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>
	<pluginRepositories>
		<pluginRepository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</pluginRepository>
	</pluginRepositories>

</project>

  • QuickStartTest02
	package com.example.shiro_demo;


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;

/*

单元测试执行顺序
@BeoreClass
 */
public class QuickStartTest02 {

    private SimpleAccountRealm accountRealm = new SimpleAccountRealm();
    private DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();

    @Before
    public void init(){
        //初始化数据源
        accountRealm.addAccount("lihw", "123");
        accountRealm.addAccount("chendan", "456");

        defaultSecurityManager.setRealm(accountRealm);
    }

    @Test
    public void testAuthentication(){
        SecurityUtils.setSecurityManager(defaultSecurityManager);

        // 当前的操作 主体
        Subject subject = SecurityUtils.getSubject();
        // 用户输入的用户名密码
        UsernamePasswordToken token = new UsernamePasswordToken("chendan", "456");

        subject.login(token);
        System.out.println("认证结果:"+ subject.isAuthenticated());
    }
}

  • QuickStartTest03
package com.example.shiro_demo;


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;

/*

单元测试执行顺序
@BeoreClass
 */
public class QuickStartTest03 {

    private SimpleAccountRealm accountRealm = new SimpleAccountRealm();
    private DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();

    @Before
    public void init(){
        //初始化数据源
        accountRealm.addAccount("lihw", "123","root", "admin");
        accountRealm.addAccount("chendan", "456", "user");

        defaultSecurityManager.setRealm(accountRealm);
    }

    @Test
    public void testAuthentication(){
        SecurityUtils.setSecurityManager(defaultSecurityManager);

        // 当前的操作 主体
        Subject subject = SecurityUtils.getSubject();
        // 用户输入的用户名密码
        UsernamePasswordToken token = new UsernamePasswordToken("chendan", "456");

        subject.login(token);
        System.out.println("认证结果:"+ subject.isAuthenticated());

        System.out.println("是否有对应角色:"+ subject.hasRole("user"));

        System.out.println("getPrincipal 认证结果:"+ subject.getPrincipal());

        // 退出
        subject.logout();

        System.out.println("---------------退出之后---------------------");

        System.out.println("认证结果:"+ subject.isAuthenticated());

        System.out.println("是否有对应角色:"+ subject.hasRole("root"));

        System.out.println("getPrincipal 认证结果:"+ subject.getPrincipal());
    }
}

  • QuickStartTesTxt
package com.example.shiro_demo;


import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.SimpleAccountRealm;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Before;
import org.junit.Test;

/*

单元测试执行顺序
@BeoreClass
 */
public class QuickStartTesTxt {



    @Before

    @Test
    public void testAuthentication(){

        Factory<SecurityManager> factory =  new IniSecurityManagerFactory("classpath:shiro.ini");
        SecurityManager securityManager = factory.getInstance();


        SecurityUtils.setSecurityManager(securityManager);

        // 当前的操作 主体
        Subject subject = SecurityUtils.getSubject();
        // 用户输入的用户名密码
        UsernamePasswordToken token = new UsernamePasswordToken("jack", "456");

        subject.login(token);
        System.out.println("认证结果:"+ subject.isAuthenticated());

        System.out.println("是否有对应角色:"+ subject.hasRole("user"));

        System.out.println("getPrincipal 认证结果:"+ subject.getPrincipal());

        System.out.println("是否有video:find权限:"+ subject.isPermitted("video:find"));

        // 退出
        subject.logout();

        System.out.println("---------------退出之后---------------------");

        System.out.println("认证结果:"+ subject.isAuthenticated());

        System.out.println("是否有对应角色:"+ subject.hasRole("root"));

        System.out.println("getPrincipal 认证结果:"+ subject.getPrincipal());
    }
}

  • shiro.ini
# 格式 name=password,role1,role2,..roleN
[users]
# user 'root' with password 'secret' and the 'admin' role,
jack = 456, user

# user 'guest' with the password 'guest' and the 'guest' role
xdcalss = 123, root


# 格式 role=permission1,permission2...permissionN   也可以用通配符
# 下面配置user的权限为所有video:find,video:buy,如果需要配置video全部操作crud 则 user = video:*
[roles]
user = video:find,video:buy
# 'admin' role has all permissions, indicated by the wildcard '*'
admin = *

  • QuickStartTesCustomRealm
package com.example.shiro_demo;


import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Before;
import org.junit.Test;

/**
 * 自定义的 realm
 */
public class QuickStartTesCustomRealm {



    @Before

    @Test
    public void testAuthentication(){

        CustomRealm customRealm = new CustomRealm();
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();

        defaultSecurityManager.setRealm(customRealm);


        SecurityUtils.setSecurityManager(defaultSecurityManager);

        // 当前的操作 主体
        Subject subject = SecurityUtils.getSubject();
        // 用户输入的用户名密码
        UsernamePasswordToken token = new UsernamePasswordToken("jack", "123");

        subject.login(token);
        System.out.println("认证结果:"+ subject.isAuthenticated());

        System.out.println("是否有对应角色:"+ subject.hasRole("user"));

        System.out.println("getPrincipal 认证结果:"+ subject.getPrincipal());

        System.out.println("是否有video:find权限:"+ subject.isPermitted("video:find"));

        // 退出
        subject.logout();

        System.out.println("---------------退出之后---------------------");

        System.out.println("认证结果:"+ subject.isAuthenticated());

        System.out.println("是否有对应角色:"+ subject.hasRole("root"));

        System.out.println("getPrincipal 认证结果:"+ subject.getPrincipal());
    }
}

  • CustomRealm
package com.example.shiro_demo;

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.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

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

public class CustomRealm extends AuthorizingRealm {

    private final Map<String, String>  userInfoMap = new HashMap<>();
    {
        userInfoMap.put("jack", "123");
        userInfoMap.put("lhw", "456");
    }

    private final Map<String, Set<String>>  permissionMap = new HashMap<>();
    {
        Set<String> set1 = new HashSet<>();
        Set<String> set2 = new HashSet<>();

        set1.add("video:find");
        set1.add("video:buy");

        set2.add("video:add");
        set2.add("video:delete");

        permissionMap.put("jack", set1);
        permissionMap.put("lihw", set2);
    }

    private final Map<String, Set<String>>  roleMap = new HashMap<>();
    {
        Set<String> set1 = new HashSet<>();
        Set<String> set2 = new HashSet<>();

        set1.add("role1");
        set1.add("role2");

        set2.add("root");


        roleMap.put("jack", set1);
        roleMap.put("lihw", set2);
    }



    /**
     * 进行权限校验的时候会调用
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("授权认证 doGetAuthorizationInfo");

        String name = (String) principalCollection.getPrimaryPrincipal();
        // 正常要从数据查找用户权限
        Set<String> permissions = getPermisstionsByNameFromDb(name);
        Set<String> roles = getRoleByNameFromDb(name);

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.setRoles(roles);
        simpleAuthorizationInfo.setStringPermissions(permissions);


        return simpleAuthorizationInfo;
    }

    private Set<String> getRoleByNameFromDb(String name) {

        return roleMap.get(name);
    }

    private Set<String> getPermisstionsByNameFromDb(String name) {

        return permissionMap.get(name);
    }


    /**
     * 用户登录的时候会调用
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("登录认证 doGetAuthenticationInfo");
        //获取用户名
        String name = (String) authenticationToken.getPrincipal();
        String pwd = userInfoMap.get(name); // 模拟从数据库拿密码

        if(pwd == null || "".equals(pwd)) {
            return null;
        }
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, pwd, this.getName());
        return simpleAuthenticationInfo;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ITzhongzi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值