一 redis的安装
参考文章:https://blog.csdn.net/u011066470/article/details/114794800
二 redis整合shiro
2.1 启动redis服务端
[root@localhost ~]# cd /usr/local/redis
[root@localhost redis]# ps -ef|grep redis
root 2947 2898 0 09:48 pts/0 00:00:00 grep --color=auto redis
[root@localhost redis]# ls
bin
[root@localhost redis]# cd bin
[root@localhost bin]# ls
dump.rdb redis-check-aof redis-cli redis-server
redis-benchmark redis-check-rdb redis-sentinel
[root@localhost bin]# ./redis-server /bonc-kecheng-jingxiang/redis-6.2.1/redis.conf
3106:C 02 Jun 2021 09:59:05.144 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
3106:C 02 Jun 2021 09:59:05.144 # Redis version=6.2.1, bits=64, commit=00000000, modified=0, pid=3106, just started
3106:C 02 Jun 2021 09:59:05.144 # Configuration loaded
3106:M 02 Jun 2021 09:59:05.144 * Increased maximum number of open files to 10032 (it was originally set to 1024).
3106:M 02 Jun 2021 09:59:05.144 * monotonic clock: POSIX clock_gettime
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 6.2.1 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
| `-._ `._ / _.-' | PID: 3106
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
3106:M 02 Jun 2021 09:59:05.145 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
3106:M 02 Jun 2021 09:59:05.145 # Server initialized
3106:M 02 Jun 2021 09:59:05.145 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
3106:M 02 Jun 2021 09:59:05.146 * Loading RDB produced by version 6.2.1
3106:M 02 Jun 2021 09:59:05.146 * RDB age 36704 seconds
3106:M 02 Jun 2021 09:59:05.146 * RDB memory usage when created 0.85 Mb
3106:M 02 Jun 2021 09:59:05.146 * DB loaded from disk: 0.001 seconds
3106:M 02 Jun 2021 09:59:05.146 * Ready to accept connections
2.2 启动redis客户端
[root@localhost ~]# cd /usr/local/redis
[root@localhost redis]# cd bin
[root@localhost bin]# ls
dump.rdb redis-check-aof redis-cli redis-server
redis-benchmark redis-check-rdb redis-sentinel
[root@localhost bin]# ./redis-cli
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379>
2.3 配置pom文件
<!--redis整合springboot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.4 配置redis连接
#redis
spring.redis.port=6379
spring.redis.host=172.16.71.22
spring.redis.database=0
2.5 开发RedisCacheManager
package com.shiro.ljf.demo.sptshirodemo.shiro.cache;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
//自定义shiro缓存管理器
public class RedisCacheManager implements CacheManager {
//参数1:认证或者是授权缓存的统一名称
@Override
public <K, V> Cache<K, V> getCache(String cacheName) throws CacheException {
System.out.println(cacheName);
return new RedisCache<K,V>(cacheName);
}
}
2.6 开RedisCache实现
package com.shiro.ljf.demo.sptshirodemo.shiro.cache;
import com.shiro.ljf.demo.sptshirodemo.utils.ApplicationContextUtils;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.util.Collection;
import java.util.Set;
//自定义redis缓存的实现
public class RedisCache<k,v> implements Cache<k,v> {
private String cacheName;
public RedisCache() {
}
public RedisCache(String cacheName) {
this.cacheName = cacheName;
}
@Override
public v get(k k) throws CacheException {
System.out.println("get key:"+k);
return (v) getRedisTemplate().opsForHash().get(this.cacheName,k.toString());
}
@Override
public v put(k k, v v) throws CacheException {
System.out.println("put key: "+k);
System.out.println("put value:"+v);
getRedisTemplate().opsForHash().put(this.cacheName,k.toString(),v);
return null;
}
@Override
public v remove(k k) throws CacheException {
System.out.println("=============remove=============");
return (v) getRedisTemplate().opsForHash().delete(this.cacheName,k.toString());
}
@Override
public void clear() throws CacheException {
System.out.println("=============clear==============");
getRedisTemplate().delete(this.cacheName);
}
@Override
public int size() {
return getRedisTemplate().opsForHash().size(this.cacheName).intValue();
}
@Override
public Set<k> keys() {
return getRedisTemplate().opsForHash().keys(this.cacheName);
}
@Override
public Collection<v> values() {
return getRedisTemplate().opsForHash().values(this.cacheName);
}
private RedisTemplate getRedisTemplate(){
RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtils.getBean("redisTemplate");
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
return redisTemplate;
}
}
2.7 自定义salt序列化
-
由于shiro中提供的simpleByteSource实现没有实现序列化,所有在认证时出现错误信息
-
解决方案: 需要自动salt实现序列化
2.自定义的myByteSource类:
package com.shiro.ljf.demo.sptshirodemo.utils;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.codec.CodecSupport;
import org.apache.shiro.codec.Hex;
import org.apache.shiro.util.ByteSource;
import java.io.File;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Arrays;
//自定义salt实现 实现序列化接口
public class MyByteSource implements ByteSource,Serializable {
private byte[] bytes;
private String cachedHex;
private String cachedBase64;
public MyByteSource(){
}
public MyByteSource(byte[] bytes) {
this.bytes = bytes;
}
public MyByteSource(char[] chars) {
this.bytes = CodecSupport.toBytes(chars);
}
public MyByteSource(String string) {
this.bytes = CodecSupport.toBytes(string);
}
public MyByteSource(ByteSource source) {
this.bytes = source.getBytes();
}
public MyByteSource(File file) {
this.bytes = (new BytesHelper()).getBytes(file);
}
public MyByteSource(InputStream stream) {
this.bytes = (new BytesHelper()).getBytes(stream);
}
public static boolean isCompatible(Object o) {
return o instanceof byte[] || o instanceof char[] || o instanceof String || o instanceof ByteSource || o instanceof File || o instanceof InputStream;
}
public byte[] getBytes() {
return this.bytes;
}
public boolean isEmpty() {
return this.bytes == null || this.bytes.length == 0;
}
public String toHex() {
if (this.cachedHex == null) {
this.cachedHex = Hex.encodeToString(this.getBytes());
}
return this.cachedHex;
}
public String toBase64() {
if (this.cachedBase64 == null) {
this.cachedBase64 = Base64.encodeToString(this.getBytes());
}
return this.cachedBase64;
}
public String toString() {
return this.toBase64();
}
public int hashCode() {
return this.bytes != null && this.bytes.length != 0 ? Arrays.hashCode(this.bytes) : 0;
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (o instanceof ByteSource) {
ByteSource bs = (ByteSource)o;
return Arrays.equals(this.getBytes(), bs.getBytes());
} else {
return false;
}
}
private static final class BytesHelper extends CodecSupport {
private BytesHelper() {
}
public byte[] getBytes(File file) {
return this.toBytes(file);
}
public byte[] getBytes(InputStream stream) {
return this.toBytes(stream);
}
}
}
2.8 验证
1.关闭防火墙
[root@localhost ~]# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2021-06-02 09:47:20 CST; 1h 17min ago
Docs: man:firewalld(1)
Main PID: 783 (firewalld)
Tasks: 2
CGroup: /system.slice/firewalld.service
└─783 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid
Jun 02 09:47:45 localhost.localdomain firewalld[783]: WARNING: COMMAND_FAILED...
Jun 02 09:47:45 localhost.localdomain firewalld[783]: WARNING: COMMAND_FAILED...
Jun 02 09:47:45 localhost.localdomain firewalld[783]: WARNING: COMMAND_FAILED...
Jun 02 09:47:45 localhost.localdomain firewalld[783]: WARNING: COMMAND_FAILED...
Jun 02 09:47:45 localhost.localdomain firewalld[783]: WARNING: COMMAND_FAILED...
Jun 02 09:47:45 localhost.localdomain firewalld[783]: WARNING: COMMAND_FAILED...
Jun 02 09:47:45 localhost.localdomain firewalld[783]: WARNING: COMMAND_FAILED...
Jun 02 09:47:45 localhost.localdomain firewalld[783]: WARNING: COMMAND_FAILED...
Jun 02 09:47:45 localhost.localdomain firewalld[783]: WARNING: COMMAND_FAILED...
Jun 02 09:47:46 localhost.localdomain firewalld[783]: WARNING: COMMAND_FAILED...
Hint: Some lines were ellipsized, use -l to show in full.
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]#
2.将服务启动起来
3.使用用户ljf进行登录
跳转到登录页面
多次刷页面
可以看到:不再查询数据库,没有查询数据库的日志,
查看redis数据库:
127.0.0.1:6379> keys *
1) "my-authenticationCache"
2) "com.shiro.ljf.demo.sptshirodemo.shiro.CustomerRealm.authorizationCache"
127.0.0.1:6379> hgetall my-authenticationCache
1) "ljf"
2) "\xac\xed\x00\x05sr\x00/org.apache.shiro.authc.SimpleAuthenticationInfo\x83\xc0\x15@`\xea%,\x02\x00\x03L\x00\x0bcredentialst\x00\x12Ljava/lang/Object;L\x00\x0fcredentialsSaltt\x00\"Lorg/apache/shiro/util/ByteSource;L\x00\nprincipalst\x00.Lorg/apache/shiro/subject/PrincipalCollection;xpt\x00 d12dfd006876d2539291d47d802b3c66sr\x002com.shiro.ljf.demo.sptshirodemo.utils.MyByteSource\xaf\x00\xe6\xbb\x05\x86\xc8\xf0\x02\x00\x03[\x00\x05bytest\x00\x02[BL\x00\x0ccachedBase64t\x00\x12Ljava/lang/String;L\x00\tcachedHexq\x00~\x00\bxpur\x00\x02[B\xac\xf3\x17\xf8\x06\bT\xe0\x02\x00\x00xp\x00\x00\x00\bQWW!RgLwppsr\x002org.apache.shiro.subject.SimplePrincipalCollection\xa8\x7fX%\xc6\xa3\bJ\x03\x00\x01L\x00\x0frealmPrincipalst\x00\x0fLjava/util/Map;xpsr\x00\x17java.util.LinkedHashMap4\xc0N\\\x10l\xc0\xfb\x02\x00\x01Z\x00\x0baccessOrderxr\x00\x11java.util.HashMap\x05\a\xda\xc1\xc3\x16`\xd1\x03\x00\x02F\x00\nloadFactorI\x00\tthresholdxp?@\x00\x00\x00\x00\x00\x0cw\b\x00\x00\x00\x10\x00\x00\x00\x01t\x005com.shiro.ljf.demo.sptshirodemo.shiro.CustomerRealm_0sr\x00\x17java.util.LinkedHashSet\xd8l\xd7Z\x95\xdd*\x1e\x02\x00\x00xr\x00\x11java.util.HashSet\xbaD\x85\x95\x96\xb8\xb74\x03\x00\x00xpw\x0c\x00\x00\x00\x10?@\x00\x00\x00\x00\x00\x01t\x00\x03ljfxx\x00w\x01\x01q\x00~\x00\x11x"
127.0.0.1:6379> hget my-authenticationCache ljf
"\xac\xed\x00\x05sr\x00/org.apache.shiro.authc.SimpleAuthenticationInfo\x83\xc0\x15@`\xea%,\x02\x00\x03L\x00\x0bcredentialst\x00\x12Ljava/lang/Object;L\x00\x0fcredentialsSaltt\x00\"Lorg/apache/shiro/util/ByteSource;L\x00\nprincipalst\x00.Lorg/apache/shiro/subject/PrincipalCollection;xpt\x00 d12dfd006876d2539291d47d802b3c66sr\x002com.shiro.ljf.demo.sptshirodemo.utils.MyByteSource\xaf\x00\xe6\xbb\x05\x86\xc8\xf0\x02\x00\x03[\x00\x05bytest\x00\x02[BL\x00\x0ccachedBase64t\x00\x12Ljava/lang/String;L\x00\tcachedHexq\x00~\x00\bxpur\x00\x02[B\xac\xf3\x17\xf8\x06\bT\xe0\x02\x00\x00xp\x00\x00\x00\bQWW!RgLwppsr\x002org.apache.shiro.subject.SimplePrincipalCollection\xa8\x7fX%\xc6\xa3\bJ\x03\x00\x01L\x00\x0frealmPrincipalst\x00\x0fLjava/util/Map;xpsr\x00\x17java.util.LinkedHashMap4\xc0N\\\x10l\xc0\xfb\x02\x00\x01Z\x00\x0baccessOrderxr\x00\x11java.util.HashMap\x05\a\xda\xc1\xc3\x16`\xd1\x03\x00\x02F\x00\nloadFactorI\x00\tthresholdxp?@\x00\x00\x00\x00\x00\x0cw\b\x00\x00\x00\x10\x00\x00\x00\x01t\x005com.shiro.ljf.demo.sptshirodemo.shiro.CustomerRealm_0sr\x00\x17java.util.LinkedHashSet\xd8l\xd7Z\x95\xdd*\x1e\x02\x00\x00xr\x00\x11java.util.HashSet\xbaD\x85\x95\x96\xb8\xb74\x03\x00\x00xpw\x0c\x00\x00\x00\x10?@\x00\x00\x00\x00\x00\x01t\x00\x03ljfxx\x00w\x01\x01q\x00~\x00\x11x"
127.0.0.1:6379>