Subject 认证主体包含两个信息
package admin.config;
import admin.filter.shiro.ShiroAuthFilter;
import admin.filter.shiro.ShiroAuthRealm;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.Filter;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Shiro配置
* @Description :
**/
@Configuration
public class ShiroConfig {
/**
* 配置安全管理器
*
* @return org.apache.shiro.mgt.SecurityManager
* @Author : Huang Yun Song
* @Date: 2020/7/16 9:18
* @Param [oAuth2Realm]
* @Description :
**/
@Bean("securityManager")
public SecurityManager securityManager(ShiroAuthRealm oAuth2Realm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联Realm
securityManager.setRealm(oAuth2Realm);
securityManager.setRememberMeManager(null);
return securityManager;
}
/**
* 配置过滤器
*
* @return org.apache.shiro.spring.web.ShiroFilterFactoryBean
* @Param [securityManager]
* @Description :
**/
@Bean("shiroFilter")
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
shiroFilter.setSecurityManager(securityManager);
//oauth过滤
//添加Shiro拦截器
/**
* Shiro 内置过滤器,可以实现权限相关的拦截器
* anon:无需认证(登录)可以直接访问
* authc:必须认证才能访问
* user:如果使用rememberMe的功能才可以访问
* perms:该资源得到资源权限才可以访问
* role:该资源必须得到角色权限才可以访问
*/
Map<String, Filter> filters = new HashMap<>();
filters.put("adminAuth", new ShiroAuthFilter());
shiroFilter.setFilters(filters);
Map<String, String> filterMap = new LinkedHashMap<>();
// filterMap.put("/favicon.ico*", "anon"); //图标
// filterMap.put("/ueditor/**", "anon"); //百度编辑器
// filterMap.put("/static/**", "anon"); //静态资源
// filterMap.put("/error", "anon"); //错误
// filterMap.put("/common/**", "anon"); //通用控制器
// filterMap.put("/robots.txt", "anon"); //SEO设置
// filterMap.put("/healthy.html", "anon"); //健康检查
// filterMap.put("/mng/login.html", "anon"); //登录页面
// filterMap.put("/mng/login", "anon"); //登录操作
// filterMap.put("/mng/checkSmsLogin", "anon"); //短信验证
// filterMap.put("/mng/getCaptcha", "anon"); //获取图形验证码
// filterMap.put("/mng/forgetPassword.html", "anon"); //忘记密码页面渲染
// filterMap.put("/mng/forgetPassword", "anon"); //忘记密码修改密码
// filterMap.put("/mng/sendSmsCode", "anon"); //发送短信验证码
// filterMap.put("/mng/sendLoginSmsCode", "anon"); //发送短信验证码
filterMap.put("/**", "adminAuth");
shiroFilter.setFilterChainDefinitionMap(filterMap);
return shiroFilter;
}
@Bean("lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
}
package admin.filter.shiro;
import basic.enums.CacheSceneEnum;
import basic.util.cache.ICache;
import common.server.sys.admin.entity.CurrAdmin;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 授权领域
*
* @Description :
* 1、检查提交的进行认证的令牌信息
* 2、根据令牌信息从数据源(通常为数据库)中获取用户信息
* 3、对用户信息进行匹配验证。
* 4、验证通过将返回一个封装了用户信息的AuthenticationInfo实例。
* 5、验证失败则抛出AuthenticationException异常信息。
**/
@Component
public class ShiroAuthRealm extends AuthorizingRealm {
protected Logger log = LoggerFactory.getLogger(ShiroAuthRealm.class);
@Autowired
ICache cache;
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof ShiroAuthToken;
}
/**
* 授权(验证权限时调用)
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
CurrAdmin currAdmin = (CurrAdmin) principals.getPrimaryPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.setStringPermissions(currAdmin.getPermissions()); //用户权限列表
return info;
}
/**
* 认证(登录时调用)
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
throws AuthenticationException {
String token = (String) authenticationToken.getPrincipal();
//根据token,查询adminId
Long adminId = cache.get(CacheSceneEnum.ADMIN_LOGIN_TOKEN.keyProfix + token, Long.class);
if (adminId == null) {
log.info("登录认证时,adminId为空");
throw new AuthenticationException("登录失效,请重新登录");
}
//根据adminId,查用户缓存信息
CurrAdmin currAdmin = cache.get(CacheSceneEnum.ADMIN_LOGIN_INFO.keyProfix + adminId, CurrAdmin.class);
if (currAdmin == null) {
log.info("登录认证时,currAdmin为空");
throw new AuthenticationException("登录失效,请重新登录");
}
if (!token.equals(currAdmin.getLoginToken())) {
log.info("登录认证时,token和当前登录管理员token不一致!");
//暂时先注释
//throw new MyShiroException(ErrorCodeEnum.FORCED_OFFLINE_ERROR);
}
//刷新登录状态
if (System.currentTimeMillis() - currAdmin.getLastSetTime() > 120000) { //3分钟更新一次缓存时间
currAdmin.setLastSetTime(System.currentTimeMillis());
cache.set(CacheSceneEnum.ADMIN_LOGIN_TOKEN.keyProfix + token, adminId,
CacheSceneEnum.ADMIN_LOGIN_TOKEN.expireTime);
cache.set(CacheSceneEnum.ADMIN_LOGIN_INFO.keyProfix + adminId, currAdmin,
CacheSceneEnum.ADMIN_LOGIN_INFO.expireTime);
}
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(currAdmin, token, getName());
return info;
}
}