安全/权限框架Shiro(1)之简介及快速开始

安全/权限框架Shiro(1)之简介及快速开始

微信搜索 zze_coding 或扫描 👉 二维码关注我的微信公众号获取更多资源推送:

介绍

概述

Apache Shiro 是 Java 的一个安全(权限)框架。

Shiro 不仅可以用在 JavaSE 环境,也可以用在 JavaEE 环境。

Shiro 可以完成:认证、授权、加密、会话管理、与 Web 集成、缓存等。

Shiro 官网:https://shiro.apache.org | 关注文章首部微信公众号发送 #116_shiro 下载源码包

功能

Apache Shiro是一个具有许多功能的综合应用程序安全框架,基本的功能如下:

image.png

Authentication:身份验证。

Authorization:授权,即访问控制的过程,指定“谁”可以访问“什么资源”。

Session Management:会话管理,即使在非 Web 或 EJB 应用程序中,也可以管理特定于用户的会话。

Cryptography:加密,使用加密算法保持数据安全,同时仍然易于使用。

快速开始

下面代码是 shiro 提供的快速开始示例,这里对其注释及提示做了中文替换易于理解,路径为 shiro-root-1.3.2\samples\quickstart

1、使用 Maven 创建 Java 工程,导入如下依赖:

<!-- pom.xml -->
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zze.shiro</groupId>
    <artifactId>shiro_test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-all</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.6.2</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.6.2</version>
        </dependency>
    </dependencies>
</project>

2、引入配置文件:

# shiro.ini
[users]
root = secret, admin
guest = guest, guest

presidentskroob = 12345, president
darkhelmet = ludicrousspeed, darklord, schwartz
lonestarr = vespa, goodguy, schwartz

[roles]
admin = *
schwartz = lightsaber:*
goodguy = winnebago:drive:eagle5
# log4j.properties
log4j.rootLogger=INFO, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n

log4j.logger.org.apache=WARN

log4j.logger.org.springframework=WARN

log4j.logger.org.apache.shiro=INFO

log4j.logger.org.apache.shiro.util.ThreadContext=WARN
log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN

3、示例代码:

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
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 Quickstart {

    private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);

    public static void main(String[] args) {
        // 加载 shiro.ini 创建 SecurityManagerFactory
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        // 获取 SecurityManager 实例
        SecurityManager securityManager = factory.getInstance();
        // 通过 SecurityUtils 操作 SecurityManager 实例
        SecurityUtils.setSecurityManager(securityManager);
        // 获得 Subject,相当于获取到当前用户
        Subject currentUser = SecurityUtils.getSubject();
        // 获得 Session
        Session session = currentUser.getSession();
        // Session 中存值
        session.setAttribute("someKey", "aValue");
        // Session 中取值
        String value = (String) session.getAttribute("someKey");
        // 判断是否取到值
        if (value.equals("aValue")) {
            log.info("获取到正确的值:[" + value + "]");
        }
        // 通过 Subject.isAuthenticated() 判断当前用户是否以认证
        if (!currentUser.isAuthenticated()) { // 如果未认证
            // 创建用户名密码Token,与 shiro.ini 中 users 下配置比对
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
            // 记住我
            token.setRememberMe(true);
            try {
                // 执行登陆操作
                currentUser.login(token);
            } catch (UnknownAccountException uae) {// 用户名不存在
                log.info("没有这个用户名的用户: " + token.getPrincipal());
            } catch (IncorrectCredentialsException ice) { // 密码错误
                log.info(token.getPrincipal() + "的密码错误");
            } catch (LockedAccountException lae) { // 账户已锁定
                log.info("用户名为" + token.getPrincipal() + "账户已锁定");
            } catch (AuthenticationException ae) { // 上面三个异常的父类
            }
        }
        // 如果已认证,currentUser.getPrincipal() 不为空
        if (currentUser.getPrincipal() != null) {
            log.info("用户 [" + currentUser.getPrincipal() + "] 登录成功");
            // 通过 Subject.hasRole() 方法判断当前用户是否拥有某个角色
            if (currentUser.hasRole("schwartz")) {
                log.info("你有[schwartz]这个角色");
            } else {
                log.info("你没有[schwartz]这个角色");
            }
            // 判断当前用户是否拥有某个权限
            // schwartz 角色对应的权限为 lightsaber:*,即可以对 lightsaber 做任何操作
            if (currentUser.isPermitted("lightsaber:weild")) {
                log.info("你可以对[lightsaber]使用[weild]");
            } else {
                log.info("对不起,[lightsaber]权限只有[schwartz]拥有");
            }
            // 更细粒度的判断当前用户是否拥有某个权限
            if (currentUser.isPermitted("winnebago:drive:eagle5")) {
                log.info("你可以[drive]标识为[eagle5]的[winnebago]");
            } else {
                log.info("对不起,你不允许[drive]标识未[eagle5]的[winnebago]");
            }
        }

        // 登出
        currentUser.logout();

        System.exit(0);
    }
}

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://www.zze.xyz/archives/shiro1.html

Buy me a cup of coffee ☕.