1、⽹站任何⻚⾯都必须登录成功之后才能浏览,除了登录⻚⾯之外。
2、登录成功之后,不同的⽤户有不同的权限。超级管理员、管理员和游客有着不同的操作权限
市面上安全拦截的技术
官网:https://shiro.apache.org/web.html
Apache Shiro是Java的一个安全(权限)框架。
Shiro可以非常容易的开发出足够好的应用,不仅可以用在JavaSE环境,也可以用在JavaEE环境。
Shiro可以完成:认证、授权、加密、会话管理、与Web集成、缓存等。
1、SecurityManager :厨师,是真正的业务操作者
2、Subject:服务员,负责提供API接⼝给⽤户使⽤。
3、SecurityUtils:餐厅,⽤来将厨师和服务员整合到⼀起,提供完整的服务。
4、Realm:材料,数据(数据库的数据),⼀般跟SecurityManager 配置使⽤
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简介说明
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);
}
}