Shiro安全框架

项目需求

1、⽹站任何⻚⾯都必须登录成功之后才能浏览,除了登录⻚⾯之外。

2、登录成功之后,不同的⽤户有不同的权限。超级管理员、管理员和游客有着不同的操作权限

市面上安全拦截的技术

  • Shiro
  • Spring Security
  • oauth2.0协议

Shiro简介

官网:https://shiro.apache.org/web.html

Apache Shiro是Java的一个安全(权限)框架。
Shiro可以非常容易的开发出足够好的应用,不仅可以用在JavaSE环境,也可以用在JavaEE环境。
Shiro可以完成:认证、授权、加密、会话管理、与Web集成、缓存等。

1、SecurityManager :厨师,是真正的业务操作者

2、Subject:服务员,负责提供API接⼝给⽤户使⽤。

3、SecurityUtils:餐厅,⽤来将厨师和服务员整合到⼀起,提供完整的服务。

4、Realm:材料,数据(数据库的数据),⼀般跟SecurityManager 配置使⽤

Shiro案例

1.新建maven项目导入Shiro依赖

    <properties>
        <maven.compiler.source>8maven.compiler.source>
        <maven.compiler.target>8maven.compiler.target>
    properties>

    <dependencies>

        <dependency>
            <groupId>org.apache.shirogroupId>
            <artifactId>shiro-coreartifactId>
            <version>1.3.2version>
        dependency>

        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.12version>
            <scope>testscope>
        dependency>

        <dependency>

            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>8.0.24version>
        dependency>

        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-jdbcartifactId>
            <version>5.1.6.RELEASEversion>
        dependency>
    dependencies>

2.测试一:

2.1在resource包下创建shiro配置文件

shiro.ini

[users]
zhangsan=123456, admin, guest
lisi=654321, guest
[roles]
admin=select, insert, delete, update
guest=select

2.2.Subject创建角色权限进行测试

TestShiro.java

package com;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
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.Test;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Scanner;

public class TestShiro {

    @Test
    public void test(){
        ///     创建IniSecurityManagerFactory,无参构造器会默认调用classpath下 shiro.ini文件
        IniSecurityManagerFactory factory = new IniSecurityManagerFactory();

        //      使用IniSecurityManagerFactory对象的getInstance()方法得到SecurityManager对象
        SecurityManager manager = factory.getInstance();

        //      使用SecurityUtils工具类的setSecurityManager()方法将SecurityManager对象存入
        SecurityUtils.setSecurityManager(manager);

        //      使用SecurityUtils工具类的getSubject()得到Subject对象
        //          subject,主体,可以使用一个“用户”, 也可以是一段程序代码或者爬虫
        Subject subject = SecurityUtils.getSubject();

        Scanner input = new Scanner(System.in);

//        System.out.println("请输入账户:");
//        String name = input.next();
        String name = "zhangsan";

//        System.out.println("请输入密码:");
//        String pass = input.next();
        String pass = "123456";


        //      使用用户输入的用户名和密码创建一个UsernamePasswordToken对象
        UsernamePasswordToken token = new UsernamePasswordToken(name, pass);

        try {

            //  使用Subject主体在指定的token之上进行登录
            subject.login(token);
        } catch (UnknownAccountException e) {
            e.printStackTrace();
        } catch (IncorrectCredentialsException e) {
            e.printStackTrace();
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }


        //  Subject的isAuthenticated()方法用来判断一个用户是否是属于认证成功
        System.out.println(subject.isAuthenticated());

        if(subject.isAuthenticated()){
            System.out.println(subject.hasRole("admin"));
            System.out.println(subject.hasRole("guest"));

            Collection<String> c = new ArrayList<>();

            c.add("admin");
            c.add("guest");
            c.add("guest02");

            System.out.println(subject.hasAllRoles(c));

            subject.checkPermission("select");
            subject.checkPermission("insert");
            subject.checkPermission("update");
            subject.checkPermission("delete");
            subject.checkPermissions("select", "delete");
        }
    }
}

Shiro Subject简介说明

Shiro详解

Subject:是Shiro的认证授权组件
   提供当前用户信息(角色 授权),然后进行登录,退出,权限验证等
   我们常将一个Subject对象称之为一个用户

什么是token

token就是令牌,前后端进行鉴权的一种有效形式,比传统的 session 鉴权更加方便,简单来说:当用户首次登陆时,网站会给你一张“门卡”,以后你可以凭借门卡直接进入,而无需再次申请。但一段时间之后门卡实效,你需要再到前台充磁,这里的门卡就是 token

session与token的区别
3.测试二

shiro02.ini

[users]
zhangsan=21218cca77804d2ba1922c33e0151105, admin, guest
lisi=654321, guest
[roles]
admin=select, insert, delete, update
guest=select
String pass = "888888";
//使用MD5加密对密码进行加密
pass = new Md5Hash(pass).toString();
 System.out.println(pass);//21218cca77804d2ba1922c33e0151105

4.测试三(验证数据库中的数据)

shiro3.ini

[main]
ds=org.springframework.jdbc.datasource.DriverManagerDataSource
ds.url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8
ds.username=root
ds.password=123456
ds.driverClassName=com.mysql.cj.jdbc.Driver

jr=org.apache.shiro.realm.jdbc.JdbcRealm
jr.dataSource=$ds
jr.authenticationQuery=select pass from users where name =?

securityManager.realm=$jr

进入源码查看,在JdbcRealm源码中可以看到已经准备好了固定的SQL语句如果自己的SQL按照同样规则编写,则在配置文件中可以省略

DriverManagerDataSource d;

JdbcRealm j;

测试类

package cqfedu;

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.Test;

public class TestShiro03 {

    @Test
    public void testShiro(){
        IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro03.ini");

        SecurityManager securityManager = factory.getInstance();

        SecurityUtils.setSecurityManager(securityManager);

        Subject subject = SecurityUtils.getSubject();

        //验证数据库信息
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "88888");

        subject.login(token);

        System.out.println(subject.isAuthenticated());
    }
}

4.密码加密

package com;

import org.apache.shiro.codec.Base64;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.junit.Test;

import java.nio.charset.StandardCharsets;

public class TestPassword {

    private String pass = "888888";

    @Test
    public void testBase64(){
        //Base64加密
        byte[] encode = Base64.encode(pass.getBytes(StandardCharsets.UTF_8));

        System.out.println(new String(encode));

        //解密
        byte[] decode = Base64.decode(encode);

        System.out.println(new String(decode));
    }

    @Test
    public void testMD5(){
        //MD5加密
//        String s = new Md5Hash(pass).toString();
        //第二个参数是为密码加盐 第三个参数是加密的循环次数 通过加盐的操作提高破译密码难度
        String s = new Md5Hash(pass,"salt",3).toString();

        System.out.println(s);
    }
}

你可能感兴趣的:(Javaweb学习笔记,安全,java,spring)