session
shiro有自己的session管理类,因为之前已经在项目中集成了spring session,shiro也可以使用spring session,只要配置shiro使用容器的session管理即可,spring session在后面拦截了容器的session实现。
@Bean(name = "securityManager")
public SecurityManager createSecurityManager(UserRealm userRealm,SessionManager shiroSessionManager) {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager(userRealm);
manager.setSessionManager(new ServletContainerSessionManager());
return manager;
}
spring session可用于分布式环境,所以在授权后,把用户信息存到session中,可以方便共享:
//验证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String userName = (String) token.getPrincipal();
String password = new String((char[]) token.getCredentials());
User user = userService.findUserByAccount(userName, password);
if (user == null) {
throw new IncorrectCredentialsException(); //如果验证失败返回错误信息
}
//如果身份认证验证成功,将用户信息保存起来
return new SimpleAuthenticationInfo(user, password, getName());
}
//登录api
try {
subject.login(token);
//if no exception, that's it, we're done!
} catch (AuthenticationException ae) {
throw new BusinessException("用户名或密码错误");
}
User user = (User) subject.getPrincipal();
subject.getSession().setAttribute("user", user); //将用户信息存放到session
//读取
//一般放到BaseController中
@Autowired
protected HttpServletRequest request;
protected User getUser() {
return (User) request.getSession().getAttribute("user");
}
cache
可以使用redis来缓存,实现shiro的CacheManager和Cache的接口即可.
SpringShiroCache.java
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.springframework.data.redis.core.ValueOperations;
import java.util.Collection;
import java.util.Set;
public class SpringShiroCache<K, V> implements Cache<K, V> {
private ValueOperations<K, V> valueOperations;
private org.springframework.cache.Cache springCache;
public SpringShiroCache(ValueOperations<K, V> valueOperations, org.springframework.cache.Cache redisCache) {
this.springCache = redisCache;
this.valueOperations = valueOperations;
}
@Override
public V get(K k) throws CacheException {
return valueOperations.get(k);
}
@Override
public V put(K k, V v) throws CacheException {
valueOperations.set(k, v);
return v;
}
@Override
public V remove(K k) throws CacheException {
V v = valueOperations.get(k);
springCache.evict(k);
return v;
}
@Override
public void clear() throws CacheException {
springCache.clear();
}
@Override
public int size() {
throw new UnsupportedOperationException();
}
@Override
public Set<K> keys() {
throw new UnsupportedOperationException();
}
@Override
public Collection<V> values() {
throw new UnsupportedOperationException();
}
}
RedisShiroCacheManager.java
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
@Component("shiroCacheManager")
public class RedisShiroCacheManager implements CacheManager {
@Autowired
private RedisCacheManager cacheManager;
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Override
public <K, V> Cache<K, V> getCache(String s) throws CacheException {
RedisTemplate<K,V> redisTemplate=new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.afterPropertiesSet();
return new SpringShiroCache<>(redisTemplate.opsForValue(),cacheManager.getCache(s));
}
}
ShiroConfig.java
//创建一个securityManager
@Bean(name = "securityManager")
public SecurityManager createSecurityManager(UserRealm userRealm, CacheManager shiroCacheManager, SessionManager shiroSessionManager) {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager(userRealm);
manager.setCacheManager(shiroCacheManager);
manager.setSessionManager(shiroSessionManager);
return manager;
}