过滤器链
@Configuration
@EnableConfigurationProperties(value = {ShiroProperties.class, RedisProperties.class})
public class ShiroAutoConfiguration {
private ShiroProperties shiroProperties;
private RedisProperties redisProperties;
public static final String SHIRO_FILTER_NAME = "shiroFilterFactoryBean";
public ShiroAutoConfiguration(ShiroProperties shiroProperties, RedisProperties redisProperties) {
this.shiroProperties = shiroProperties;
this.redisProperties = redisProperties;
}
/**
* 创建凭证匹配器
*/
@Bean
public HashedCredentialsMatcher getHashedCredentialsMatcher() {
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
//注入散列算法名
matcher.setHashAlgorithmName(shiroProperties.getHashAlgorithmName());
//注入散列次数
matcher.setHashIterations(shiroProperties.getHashIterations());
return matcher;
}
/**
* 创建自定义realm
* 并注入凭证匹配器
*/
@Bean
@ConditionalOnClass(value = {UserRealm.class})
public UserRealm getUserRealm(HashedCredentialsMatcher matcher) {
UserRealm userRealm = new UserRealm();
//注入凭证匹配器
userRealm.setCredentialsMatcher(matcher);
return userRealm;
}
/**
* 创建安全管理器
*/
@Bean
@ConditionalOnClass(value = DefaultWebSecurityManager.class)
public DefaultWebSecurityManager getSecurityManager(DefaultWebSessionManager defaultWebSessionManager, UserRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//注入realm
securityManager.setRealm(userRealm);
securityManager.setSessionManager(defaultWebSessionManager);
return securityManager;
}
/**
* -声明过滤器
* Shiro 的Web过滤器 id必须和web.xml里面的shiroFilter的 targetBeanName的值一样
*/
@Bean(value = SHIRO_FILTER_NAME)
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//注入安全管理器
bean.setSecurityManager(securityManager);
//处理用户未认证访问要认证的地址的跳转问题 默认是跳转到shiroProperties.getLoginUrl()现在改成以json串形式返回
Map<String, Filter> filters = new HashMap<>();
filters.put("authc", new ShiroLoginFilter());
bean.setFilters(filters);
Map<String, String> map = new HashMap<>();
//配置不拦击的路径
String[] anonUrls = shiroProperties.getAnonUrls();
if (anonUrls != null && anonUrls.length > 0) {
for (String anonUrl : anonUrls) {
map.put(anonUrl, "anon");
}
}
//配置拦截的路径
String[] authcUrls = this.shiroProperties.getAuthcUrls();
if (authcUrls != null && authcUrls.length > 0) {
for (String authcUrl : authcUrls) {
map.put(authcUrl, "authc");
}
}
bean.setFilterChainDefinitionMap(map);
return bean;
}
/**
* sessionManager 里面可以决定sessionDAO
* @param redisSessionDao
* defaultWebSessionManager来源com.sxt.system.config.TokenWebSessionManager
* @return
*/
@Bean
public DefaultWebSessionManager defaultWebSessionManager(RedisSessionDAO redisSessionDao) {
DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager();
defaultWebSessionManager.setSessionDAO(redisSessionDao);
return defaultWebSessionManager;
}
/**
* 使用Redis 来存储登录的信息
* sessionDao 还需要设置给sessionManager
*/
@Bean
public RedisSessionDAO redisSessionDAO(IRedisManager redisManager) {
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(redisManager); //操作那个redis
redisSessionDAO.setExpire(7 * 24 * 3600); // 用户的登录信息保存多久? 7 天
return redisSessionDAO;
}
/**
* 因为分步式项目,所以使用redis去存我们的登陆Session
* @return
*/
@Bean
public IRedisManager redisManager() {
//因为RedisManager要操作redis所以必须把Redis的客户端给RedisManager
RedisManager redisManager = new RedisManager();
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
JedisPool jedisPool = new JedisPool(jedisPoolConfig, redisProperties.getHost(), redisProperties.getPort(), 5000, redisProperties.getPassword());
redisManager.setJedisPool(jedisPool);
return redisManager;
}
}
登录认证类
public class UserRealm extends AuthorizingRealm {
@Autowired
@Lazy
private UserService userService;
@Override
public String getName() {
return this.getClass().getSimpleName();
}
/**
* 做认证 --就是登陆
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//得到用户登陆名
String phone=token.getPrincipal().toString();
//根据电话查询用户是否存在
User user = userService.queryUserByPhone(phone);
if(null!=user){//说明用户存在,但是密码可能不正确
//组装存放到reids里面的对象
ActiverUser activerUser=new ActiverUser();
activerUser.setUser(user);
//匹配密码
SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(
activerUser,user.getPassword(), ByteSource.Util.bytes(user.getSalt()),this.getName());
return info;
}else{
return null;//代表用户不存在
}
}
/**
* 做授权 --登陆成功之后判断用户是否有某个菜单或按钮的权限
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
ActiverUser activerUser= (ActiverUser) principals.getPrimaryPrincipal();//身份得到的就是上一个方法的返回值的值 第一个参数activerUser
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
return info;
}
}