Shiro安全框架学习(一) —— 基于ini配置文件的shiro入门

Shiro 概念

安全应该是互联网公司的一道生命线,几乎任何的公司都会涉及到这方面的需求。在Java领域一般有Spring Security、Apache Shiro等安全框架,但是由于Spring Security过于庞大和复杂,大多数公司会选择Apache Shiro来使用。

Apache Shiro是一个功能强大、灵活的,开源的安全框架。

  • 在使用Shiro 之前,大家做登录,权限什么的都是五花八门,各种花里胡哨的代码,不同系统的做法很有可能千差万别。
  • 但是使用 Shiro 这个安全框架之后,大家做权限的方式都一致化了,这样的好处就是你的代码我看起来容易,我的代码你也好理解。
  • Shiro 也比较成熟,基本上能满足大部分的权限需要。

Shiro能做什么呢?

  • 验证用户身份
  • 用户访问权限控制,比如:1、判断用户是否分配了一定的安全角色。2、判断用户是否被授予完成某个操作的权限
  • 在非 web 或 EJB 容器的环境下可以任意使用Session API
  • 可以响应认证、访问控制,或者 Session 生命周期中发生的事件
  • 可将一个或以上用户安全数据源数据组合成一个复合的用户 “view”(视图)
  • 支持单点登录(SSO)功能
  • 支持提供“Remember Me”服务,获取用户关联信息而无需登录

等等——都集成到一个有凝聚力的易于使用的API。


1,先来个最简单的,两下就跑起来的基于ini配置文件的shiro 入门

shiro.ini文件

在src目录下新建 shiro.ini
这里面定义了和安全相关的数据: 用户,角色和权限

#定义用户
[users]
#用户名 zhang3  密码是 12345, 角色是 admin
zhang3 = 12345, admin
#用户名 li4  密码是 abcde, 角色是 产品经理
li4 = abcde,productManager
#定义角色
[roles]
#管理员什么都能做
admin = *
#产品经理只能做产品管理
productManager = addProduct,deleteProduct,editProduct,updateProduct,listProduct
#订单经理只能做订单管理
orderManager = addOrder,deleteOrder,editOrder,updateOrder,listOrder

User

准备用户类,用于存放账号密码

package com.how2java;
 
public class User {
 
    private String name;
    private String password;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
     
}


TestShiro

准备3个用户,前两个能在 shiro.ini 中找到,第3个不存在
然后测试登录
接着测试是否包含角色
最后测试是否拥有权限

注:Subject 在 Shiro 这个安全框架下, Subject 就是当前用户


package com.how2java;
import java.util.ArrayList;
import java.util.List;
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.apache.shiro.util.Factory;

public class TestShiro {
    public static void main(String[] args) {
        //用户们
        User zhang3 = new User();
        zhang3.setName("zhang3");
        zhang3.setPassword("12345");

        User li4 = new User();
        li4.setName("li4");
        li4.setPassword("abcde");

        User wang5 = new User(); //wang5用户在shiro.ini中并没有配置
        wang5.setName("wang5");
        wang5.setPassword("wrongpassword");

        List<User> users = new ArrayList<>();

        users.add(zhang3);
        users.add(li4);
        users.add(wang5);

        //角色们
        String roleAdmin = "admin";
        String roleProductManager ="productManager";

        List<String> roles = new ArrayList<>();
        roles.add(roleAdmin);
        roles.add(roleProductManager);

        //权限们
        String permitAddProduct = "addProduct";
        String permitAddOrder = "addOrder";

        List<String> permits = new ArrayList<>();
        permits.add(permitAddProduct);
        permits.add(permitAddOrder);

        //登陆每个用户
        for (User user : users) {
            if(login(user)) //判断用户能够登录(账号、密码),调用login()方法
                System.out.printf("%s \t成功登陆,用的密码是 %s\t %n",user.getName(),user.getPassword());
            else
                System.out.printf("%s \t成功失败,用的密码是 %s\t %n",user.getName(),user.getPassword());
        }

        System.out.println("-------how2j 分割线------");

        //判断能够登录的用户是否拥有某个角色
        for (User user : users) {
            for (String role : roles) {
                if(login(user)) {
                    if(hasRole(user, role)) //调用hasRole()方法
                        System.out.printf("%s\t 拥有角色: %s\t%n",user.getName(),role);
                    else
                        System.out.printf("%s\t 不拥有角色: %s\t%n",user.getName(),role);
                }
            }
        }
        System.out.println("-------how2j 分割线------");

        //判断能够登录的用户,是否拥有某种权限
        for (User user : users) {
            for (String permit : permits) {
                if(login(user)) {
                    if(isPermitted(user, permit)) //调用isPermitted()方法
                        System.out.printf("%s\t 拥有权限: %s\t%n",user.getName(),permit);
                    else
                        System.out.printf("%s\t 不拥有权限: %s\t%n",user.getName(),permit);
                }
            }
        }
    }

    private static boolean hasRole(User user, String role){
        Subject subject = getSubject();
        return subject.hasRole(role);
    }

    private static boolean isPermitted(User user, String permit){
        Subject subject = getSubject();
        return subject.isPermitted(permit);
    }

    private static Subject getSubject(){
        //加载配置文件,并获取工厂
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        //获取安全管理者实例
        SecurityManager sm = factory.getInstance();
        //将安全管理者实例放入全局对象
        SecurityUtils.setSecurityManager(sm);
        //全局对象通过安全管理者生成Subject对象
        Subject subject = SecurityUtils.getSubject();

        return subject;
    }

    private static boolean login(User user){
        Subject subject = getSubject();
        //如果已经登录过了,退出
        if(subject.isAuthenticated()) {
            subject.logout();
        }
        //封装用户的数据
        UsernamePasswordToken token = new UsernamePasswordToken(user.getName(),user.getPassword());
        try{
            subject.login(token);
        }catch(AuthenticationException e){
            return false;
        }
        return subject.isAuthenticated();
    }
}

简单了解:

isAuthenticated():

用户身份识别,通常被称为用户“登录”
已验证(Authenticated):一个被验证的Subject是成功验证后(如登录成功)并存于当前session中,一个被认为验证过的对象调用subject.isAuthenticated()将返回真。


logout():

当你调用logout,任何现存的session将变为不可用并且所有的身份信息将消失(如:在web程序中,RememberMe的Cookie信息同样被删除)。


  • Subject:当前用户,Subject 可以是一个人,但也可以是第三方服务、守护进程帐户、时钟守护任务或者其它–当前和软件交互的任何事件。
  • SecurityManager:管理所有Subject,SecurityManager 是 Shiro 架构的核心,配合内部安全组件共同组成安全伞。
  • UsernamePasswordToken:是最常见的用户名/密码的认证机制。

参考来源于:

http://how2j.cn/k/shiro/shiro-tutorial/1720.html      源代码来源how2java

http://blog.sina.com.cn/s/blog_804c1dce0102x15w.html

http://www.ityouknow.com/springboot/2017/06/26/springboot-shiro.html

猜你喜欢

转载自blog.csdn.net/weixin_41888813/article/details/81354569
今日推荐