1.近期在弄shiro的安全框架,目前情况是后端使用form请求进行登录,前端使用ajax进行登录。一是为减少重复代码编写,二是为了深入了解shiro的一些知识。
2.后端框架使用ssm + shiro1.2.3,缓存方面主要用ehcache2.6.11或者redis,主要的shiro pom依赖有如下:
<properties>
<shiro.version>1.2.3</shiro.version>
</properties>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-cas</artifactId>
<version>${shiro.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>${shiro.version}</version>
</dependency>
3.spring配置shiro
<!-- Shiro权限过滤过滤器定义 -->
<bean name="shiroFilterChainDefinitions" class="java.lang.String">
<constructor-arg>
<value>
/open/smartFactory/** = authc
/weixin/** = anon
/static/** = anon
/userfiles/** = anon
${adminPath}/cas = cas
${adminPath}/login = authc
${adminPath}/logout = logout
${adminPath}/** = user
/act/editor/** = user
/ReportServer/** = user
</value>
</constructor-arg>
</bean>
<!-- 安全认证过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="${adminPath}/login" />
<property name="successUrl" value="${adminPath}?login" />
<property name="filters">
<map>
<entry key="cas" value-ref="casFilter"/>
<entry key="authc" value-ref="formAuthenticationFilter"/>
</map>
</property>
<property name="filterChainDefinitions">
<ref bean="shiroFilterChainDefinitions"/>
</property>
</bean>
<!-- CAS认证过滤器 -->
<bean id="casFilter" class="org.apache.shiro.cas.CasFilter">
<property name="failureUrl" value="${adminPath}/login"/>
</bean>
<!-- 定义Shiro安全管理配置 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="systemAuthorizingRealm" />
<property name="sessionManager" ref="sessionManager" />
<property name="cacheManager" ref="shiroCacheManager" />
</bean>
<!-- 自定义会话管理配置 -->
<bean id="sessionManager" class="com.thinkgem.jeesite.common.security.shiro.session.SessionManager">
<property name="sessionDAO" ref="sessionDAO"/>
<!-- 会话超时时间,单位:毫秒 -->
<property name="globalSessionTimeout" value="${session.sessionTimeout}"/>
<!-- 定时清理失效会话, 清理用户直接关闭浏览器造成的孤立会话 -->
<property name="sessionValidationInterval" value="${session.sessionTimeoutClean}"/>
<!-- <property name="sessionValidationSchedulerEnabled" value="false"/> -->
<property name="sessionValidationSchedulerEnabled" value="true"/>
<property name="sessionIdCookie" ref="sessionIdCookie"/>
<property name="sessionIdCookieEnabled" value="true"/>
</bean>
<!-- 指定本系统SESSIONID, 默认为: JSESSIONID 问题: 与SERVLET容器名冲突, 如JETTY, TOMCAT 等默认JSESSIONID,
当跳出SHIRO SERVLET时如ERROR-PAGE容器会为JSESSIONID重新分配值导致登录会话丢失! -->
<bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg name="name" value="jeesite.session.id"/>
</bean>
<!-- 自定义Session存储容器 -->
<!-- <bean id="sessionDAO" class="com.thinkgem.jeesite.common.security.shiro.session.JedisSessionDAO"> -->
<!-- <property name="sessionIdGenerator" ref="idGen" /> -->
<!-- <property name="sessionKeyPrefix" value="${redis.keyPrefix}_session_" /> -->
<!-- </bean> -->
<bean id="sessionDAO" class="com.thinkgem.jeesite.common.security.shiro.session.CacheSessionDAO">
<property name="sessionIdGenerator" ref="idGen" />
<property name="activeSessionsCacheName" value="activeSessionsCache" />
<property name="cacheManager" ref="shiroCacheManager" />
</bean>
<!-- 自定义系统缓存管理器-->
<!-- <bean id="shiroCacheManager" class="com.thinkgem.jeesite.common.security.shiro.cache.JedisCacheManager"> -->
<!-- <property name="cacheKeyPrefix" value="${redis.keyPrefix}_cache_" /> -->
<!-- </bean> -->
<bean id="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManager" ref="cacheManager"/>
</bean>
<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- AOP式方法级权限检查 -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true" />
</bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
4.shiro的登录
@Service
public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.FormAuthenticationFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(FormAuthenticationFilter.class);
public static final String DEFAULT_CAPTCHA_PARAM = "validateCode";
public static final String DEFAULT_MOBILE_PARAM = "mobileLogin";
public static final String DEFAULT_MESSAGE_PARAM = "message";
private String captchaParam = DEFAULT_CAPTCHA_PARAM;
private String mobileLoginParam = DEFAULT_MOBILE_PARAM;
private String messageParam = DEFAULT_MESSAGE_PARAM;
protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
String username = getUsername(request);
String password = getPassword(request);
if (password == null) {
password = "";
}
boolean rememberMe = isRememberMe(request);
String host = StringUtils.getRemoteAddr((HttpServletRequest) request);
String captcha = getCaptcha(request);
boolean mobile = isMobileLogin(request);
return new UsernamePasswordToken(username, password.toCharArray(), rememberMe, host, captcha, mobile);
}
/**
* 每次请求的时候都先进入此方法
*
* @param request
* @param response
* @return
* @throws Exception
*/
@Override
protected boolean onAccessDenied(ServletRequest request,
ServletResponse response) throws Exception {
HttpServletResponse resp = (HttpServletResponse) response;
HttpServletRequest resq = (HttpServletRequest) request;
// 后台form
if (isLoginRequest(request, response)) {
if (isLoginSubmission(request, response)) {
return executeLogin(request, response);
} else {
return true;
}
} else {
// ajax请求
if ("XMLHttpRequest"
.equalsIgnoreCase(((HttpServletRequest) request)
.getHeader("X-Requested-With"))) {
saveRequestAndRedirectToLogin(request, response);
} else {
request.setCharacterEncoding("utf-8");
resp.setHeader("Content-type", "text/html;charset=UTF-8");
resp.setCharacterEncoding("utf-8");
Result result = ResultGenerator.getNotLoginResult(
new String("没有登录,请登录".getBytes(), "UTF-8"));
resp.getWriter().write(JSON.toJSONString(result));
resp.getWriter().flush();
resp.getWriter().close();
}
return false;
}
}
/**
* 获取登录用户名
*/
protected String getUsername(ServletRequest request, ServletResponse response) {
String username = super.getUsername(request);
if (StringUtils.isBlank(username)) {
username = StringUtils.toString(request.getAttribute(getUsernameParam()), StringUtils.EMPTY);
}
return username;
}
/**
* 获取登录密码
*/
@Override
protected String getPassword(ServletRequest request) {
String password = super.getPassword(request);
if (StringUtils.isBlank(password)) {
password = StringUtils.toString(request.getAttribute(getPasswordParam()), StringUtils.EMPTY);
}
return password;
}
/**
* 获取记住我
*/
@Override
protected boolean isRememberMe(ServletRequest request) {
String isRememberMe = WebUtils.getCleanParam(request, getRememberMeParam());
if (StringUtils.isBlank(isRememberMe)) {
isRememberMe = StringUtils.toString(request.getAttribute(getRememberMeParam()), StringUtils.EMPTY);
}
return StringUtils.toBoolean(isRememberMe);
}
public String getCaptchaParam() {
return captchaParam;
}
protected String getCaptcha(ServletRequest request) {
return WebUtils.getCleanParam(request, getCaptchaParam());
}
public String getMobileLoginParam() {
return mobileLoginParam;
}
protected boolean isMobileLogin(ServletRequest request) {
return WebUtils.isTrue(request, getMobileLoginParam());
}
public String getMessageParam() {
return messageParam;
}
/**
* 登录成功之后跳转URL
*/
public String getSuccessUrl() {
return super.getSuccessUrl();
}
@Override
protected void issueSuccessRedirect(ServletRequest request,
ServletResponse response) throws Exception {
SystemAuthorizingRealm.Principal p = UserUtils.getPrincipal();
if (p != null && !p.isMobileLogin()) {
WebUtils.issueRedirect(request, response, getSuccessUrl(), null, true);
}
// else {
// super.issueSuccessRedirect(request, response);
// }
}
/**
* 登录成功回调
*
* @param token
* @param subject
* @param request
* @param response
* @return
* @throws Exception
*/
@Override
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest resq = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
// 返回ajax数据
if (!isBackground(request)) {
request.setCharacterEncoding("utf-8");
resp.setHeader("Content-type", "text/html;charset=UTF-8");
resp.setCharacterEncoding("utf-8");
String tokenId = (String) UserUtils.getSession().getId();
Map tokenMap = Maps.newHashMapWithExpectedSize(1);
tokenMap.put(Global.TOKEN, tokenId);
Result result = ResultGenerator.getSuccessResult(tokenMap);
response.getWriter().write(JSON.toJSONString(result));
response.getWriter().flush();
response.getWriter().close();
} else {
// modelandview方式
issueSuccessRedirect(request, response);
}
return false;
}
/**
* 登录失败调用事件
*/
@Override
protected boolean onLoginFailure(AuthenticationToken token,
AuthenticationException e, ServletRequest request, ServletResponse response) {
HttpServletResponse resp = (HttpServletResponse) response;
String className = e.getClass().getName(), message = "";
// 返回json格式信息
if (IncorrectCredentialsException.class.getName().equals(className)
|| UnknownAccountException.class.getName().equals(className)) {
message = "用户或密码错误, 请重试.";
} else if (e.getMessage() != null && StringUtils.startsWith(e.getMessage(), "msg:")) {
message = StringUtils.replace(e.getMessage(), "msg:", "");
} else {
message = "系统出现点问题,请稍后再试!";
e.printStackTrace(); // 输出到控制台
}
Result result = ResultGenerator.getFailResult(message);
// 返回ajax信息
if (!isBackground(request)) {
try {
request.setCharacterEncoding("utf-8");
resp.setHeader("Content-type", "text/html;charset=UTF-8");
resp.setCharacterEncoding("utf-8");
response.getWriter().write(JSON.toJSONString(result));
response.getWriter().flush();
response.getWriter().close();
} catch (IOException e1) {
e1.printStackTrace();
}
} else {
request.setAttribute(getFailureKeyAttribute(), className);
request.setAttribute(getMessageParam(), message);
}
return true;
}
private boolean isBackground(ServletRequest request) {
if ("XMLHttpRequest"
.equalsIgnoreCase(((HttpServletRequest) request)
.getHeader("X-Requested-With"))) {
return true;
}
return false;
}
}
5.系统的认证实现类
@Service
//@DependsOn({"userDao","roleDao","menuDao"})
public class SystemAuthorizingRealm extends AuthorizingRealm {
private Logger logger = LoggerFactory.getLogger(getClass());
private SystemService systemService;
public SystemAuthorizingRealm() {
this.setCachingEnabled(false);
}
@Override
protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {
super.assertCredentialsMatch(token, info);
}
/**
* 认证回调函数, 登录时调用
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
int activeSessionSize = getSystemService().getSessionDao().getActiveSessions(false).size();
if (logger.isDebugEnabled()){
logger.debug("login submit, active session size: {}, username: {}", activeSessionSize, token.getUsername());
}
// 校验登录验证码
if (LoginController.isValidateCodeLogin(token.getUsername(), false, false)){
Session session = UserUtils.getSession();
String code = (String)session.getAttribute(ValidateCodeServlet.VALIDATE_CODE);
if (token.getCaptcha() == null || !token.getCaptcha().toUpperCase().equals(code)){
throw new AuthenticationException("msg:验证码错误, 请重试.");
}
}
// 校验用户名密码
User user = getSystemService().getUserByLoginName(token.getUsername());
if (user != null) {
if (Global.NO.equals(user.getLoginFlag())){
throw new AuthenticationException("msg:该已帐号禁止登录.");
}
byte[] salt = Encodes.decodeHex(user.getPassword().substring(0,16));
return new SimpleAuthenticationInfo(new Principal(user, token.isMobileLogin()),
user.getPassword().substring(16), ByteSource.Util.bytes(salt), getName());
} else {
return null;
}
}
/**
* 获取权限授权信息,如果缓存中存在,则直接从缓存中获取,否则就重新获取, 登录成功后调用
*/
protected AuthorizationInfo getAuthorizationInfo(PrincipalCollection principals) {
if (principals == null) {
return null;
}
AuthorizationInfo info = null;
info = (AuthorizationInfo)UserUtils.getCache(UserUtils.CACHE_AUTH_INFO);
if (info == null) {
info = doGetAuthorizationInfo(principals);
if (info != null) {
UserUtils.putCache(UserUtils.CACHE_AUTH_INFO, info);
}
}
return info;
}
/**
* 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
Principal principal = (Principal) getAvailablePrincipal(principals);
// 获取当前已登录的用户
if (!Global.TRUE.equals(Global.getConfig("user.multiAccountLogin"))){
Collection<Session> sessions = getSystemService().getSessionDao().getActiveSessions(true, principal, UserUtils.getSession());
if (sessions.size() > 0){
// 如果是登录进来的,则踢出已在线用户
if (UserUtils.getSubject().isAuthenticated()){
for (Session session : sessions){
getSystemService().getSessionDao().delete(session);
}
}
// 记住我进来的,并且当前用户已登录,则退出当前用户提示信息。
else{
UserUtils.getSubject().logout();
throw new AuthenticationException("msg:账号已在其它地方登录,请重新登录。");
}
}
}
User user = getSystemService().getUserByLoginName(principal.getLoginName());
if (user != null) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
List<Menu> list = UserUtils.getMenuList();
for (Menu menu : list){
if (StringUtils.isNotBlank(menu.getPermission())){
// 添加基于Permission的权限信息
for (String permission : StringUtils.split(menu.getPermission(),",")){
info.addStringPermission(permission);
}
}
}
// 添加用户权限
info.addStringPermission("user");
// 添加用户角色信息
for (Role role : user.getRoleList()){
info.addRole(role.getEnname());
}
// 更新登录IP和时间
getSystemService().updateUserLoginInfo(user);
// 记录登录日志
LogUtils.saveLog(Servlets.getRequest(), "系统登录");
return info;
} else {
return null;
}
}
@Override
protected void checkPermission(Permission permission, AuthorizationInfo info) {
authorizationValidate(permission);
super.checkPermission(permission, info);
}
@Override
protected boolean[] isPermitted(List<Permission> permissions, AuthorizationInfo info) {
if (permissions != null && !permissions.isEmpty()) {
for (Permission permission : permissions) {
authorizationValidate(permission);
}
}
return super.isPermitted(permissions, info);
}
@Override
public boolean isPermitted(PrincipalCollection principals, Permission permission) {
authorizationValidate(permission);
return super.isPermitted(principals, permission);
}
@Override
protected boolean isPermittedAll(Collection<Permission> permissions, AuthorizationInfo info) {
if (permissions != null && !permissions.isEmpty()) {
for (Permission permission : permissions) {
authorizationValidate(permission);
}
}
return super.isPermittedAll(permissions, info);
}
/**
* 授权验证方法
* @param permission
*/
private void authorizationValidate(Permission permission){
// 模块授权预留接口
}
/**
* 设定密码校验的Hash算法与迭代次数
*/
@PostConstruct
public void initCredentialsMatcher() {
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(SystemService.HASH_ALGORITHM);
matcher.setHashIterations(SystemService.HASH_INTERATIONS);
setCredentialsMatcher(matcher);
}
// /**
// * 清空用户关联权限认证,待下次使用时重新加载
// */
// public void clearCachedAuthorizationInfo(Principal principal) {
// SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
// clearCachedAuthorizationInfo(principals);
// }
/**
* 清空所有关联认证
* @Deprecated 不需要清空,授权缓存保存到session中
*/
@Deprecated
public void clearAllCachedAuthorizationInfo() {
// Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
// if (cache != null) {
// for (Object key : cache.keys()) {
// cache.remove(key);
// }
// }
}
/**
* 获取系统业务对象
*/
public SystemService getSystemService() {
if (systemService == null){
systemService = SpringContextHolder.getBean(SystemService.class);
}
return systemService;
}
/**
* 授权用户信息
*/
public static class Principal implements Serializable {
private static final long serialVersionUID = 1L;
private String id; // 编号
private String loginName; // 登录名
private String name; // 姓名
private boolean mobileLogin; // 是否手机登录
// private Map<String, Object> cacheMap;
public Principal(User user, boolean mobileLogin) {
this.id = user.getId();
this.loginName = user.getLoginName();
this.name = user.getName();
this.mobileLogin = mobileLogin;
}
public String getId() {
return id;
}
public String getLoginName() {
return loginName;
}
public String getName() {
return name;
}
public boolean isMobileLogin() {
return mobileLogin;
}
// @JsonIgnore
// public Map<String, Object> getCacheMap() {
// if (cacheMap==null){
// cacheMap = new HashMap<String, Object>();
// }
// return cacheMap;
// }
/**
* 获取SESSIONID
*/
public String getSessionid() {
try{
return (String) UserUtils.getSession().getId();
}catch (Exception e) {
return "";
}
}
@Override
public String toString() {
return id;
}
}
}
6.UsernamePasswordToken
public class UsernamePasswordToken extends org.apache.shiro.authc.UsernamePasswordToken {
private static final long serialVersionUID = 1L;
private String captcha;
private boolean mobileLogin;
public UsernamePasswordToken() {
super();
}
public UsernamePasswordToken(String username, char[] password,
boolean rememberMe, String host, String captcha, boolean mobileLogin) {
super(username, password, rememberMe, host);
this.captcha = captcha;
this.mobileLogin = mobileLogin;
}
public String getCaptcha() {
return captcha;
}
public void setCaptcha(String captcha) {
this.captcha = captcha;
}
public boolean isMobileLogin() {
return mobileLogin;
}
}
7.sessionDao
public interface SessionDAO extends org.apache.shiro.session.mgt.eis.SessionDAO {
/**
* 获取活动会话
* @param includeLeave 是否包括离线(最后访问时间大于3分钟为离线会话)
* @return
*/
public Collection<Session> getActiveSessions(boolean includeLeave);
/**
* 获取活动会话
* @param includeLeave 是否包括离线(最后访问时间大于3分钟为离线会话)
* @param principal 根据登录者对象获取活动会话
* @param filterSession 不为空,则过滤掉(不包含)这个会话。
* @return
*/
public Collection<Session> getActiveSessions(boolean includeLeave, Object principal, Session filterSession);
}
7.自定义web会话管理类
public class SessionManager extends DefaultWebSessionManager {
private static final Logger LOGGER = LoggerFactory.getLogger(SessionManager.class);
public SessionManager() {
super();
}
@Override
protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
LOGGER.info("根据token获取sessionID,确定用户是否登录");
// 如果参数中包含“__sid”参数,则使用此sid会话。 例如:http://localhost/project?__sid=xxx&__cookie=true
String sid = request.getParameter("__sid");
if (StringUtils.isNotBlank(sid)) {
// 是否将sid保存到cookie,浏览器模式下使用此参数。
if (WebUtils.isTrue(request, "__cookie")) {
HttpServletRequest rq = (HttpServletRequest) request;
HttpServletResponse rs = (HttpServletResponse) response;
Cookie template = getSessionIdCookie();
Cookie cookie = new SimpleCookie(template);
cookie.setValue(sid);
cookie.saveTo(rq, rs);
}
// 设置当前session状态
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
ShiroHttpServletRequest.URL_SESSION_ID_SOURCE); // session来源与url
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sid);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
return sid;
} else {
return super.getSessionId(request, response);
}
}
@Override
public void validateSessions() {
super.validateSessions();
}
@Override
protected Session retrieveSession(SessionKey sessionKey) {
try {
return super.retrieveSession(sessionKey);
} catch (UnknownSessionException e) {
// 获取不到SESSION不抛出异常
return null;
}
}
public Date getStartTimestamp(SessionKey key) {
try {
return super.getStartTimestamp(key);
} catch (InvalidSessionException e) {
// 获取不到SESSION不抛出异常
return null;
}
}
public Date getLastAccessTime(SessionKey key) {
try {
return super.getLastAccessTime(key);
} catch (InvalidSessionException e) {
// 获取不到SESSION不抛出异常
return null;
}
}
public long getTimeout(SessionKey key) {
try {
return super.getTimeout(key);
} catch (InvalidSessionException e) {
// 获取不到SESSION不抛出异常
return 0;
}
}
public void setTimeout(SessionKey key, long maxIdleTimeInMillis) {
try {
super.setTimeout(key, maxIdleTimeInMillis);
} catch (InvalidSessionException e) {
// 获取不到SESSION不抛出异常
}
}
public void touch(SessionKey key) {
try {
super.touch(key);
} catch (InvalidSessionException e) {
// 获取不到SESSION不抛出异常
}
}
public String getHost(SessionKey key) {
try {
return super.getHost(key);
} catch (InvalidSessionException e) {
// 获取不到SESSION不抛出异常
return null;
}
}
public Collection<Object> getAttributeKeys(SessionKey key) {
try {
return super.getAttributeKeys(key);
} catch (InvalidSessionException e) {
// 获取不到SESSION不抛出异常
return null;
}
}
public Object getAttribute(SessionKey sessionKey, Object attributeKey) {
try {
return super.getAttribute(sessionKey, attributeKey);
} catch (InvalidSessionException e) {
// 获取不到SESSION不抛出异常
return null;
}
}
public void setAttribute(SessionKey sessionKey, Object attributeKey, Object value) {
try {
super.setAttribute(sessionKey, attributeKey, value);
} catch (InvalidSessionException e) {
// 获取不到SESSION不抛出异常
}
}
public Object removeAttribute(SessionKey sessionKey, Object attributeKey) {
try {
return super.removeAttribute(sessionKey, attributeKey);
} catch (InvalidSessionException e) {
// 获取不到SESSION不抛出异常
return null;
}
}
public void stop(SessionKey key) {
try {
super.stop(key);
} catch (InvalidSessionException e) {
// 获取不到SESSION不抛出异常
}
}
public void checkValid(SessionKey key) {
try {
super.checkValid(key);
} catch (InvalidSessionException e) {
// 获取不到SESSION不抛出异常
}
}
@Override
protected Session doCreateSession(SessionContext context) {
try {
return super.doCreateSession(context);
} catch (IllegalStateException e) {
return null;
}
}
@Override
protected Session newSessionInstance(SessionContext context) {
Session session = super.newSessionInstance(context);
session.setTimeout(getGlobalSessionTimeout());
return session;
}
@Override
public Session start(SessionContext context) {
try {
return super.start(context);
} catch (NullPointerException e) {
SimpleSession session = new SimpleSession();
session.setId(0);
return session;
}
}
}
8.session缓存dao
public class CacheSessionDAO extends EnterpriseCacheSessionDAO implements SessionDAO {
private Logger logger = LoggerFactory.getLogger(getClass());
public CacheSessionDAO() {
super();
}
@Override
protected void doUpdate(Session session) {
if (session == null || session.getId() == null) {
return;
}
HttpServletRequest request = Servlets.getRequest();
if (request != null){
String uri = request.getServletPath();
// 如果是静态文件,则不更新SESSION
if (Servlets.isStaticFile(uri)){
return;
}
// 如果是视图文件,则不更新SESSION
if (StringUtils.startsWith(uri, Global.getConfig("web.view.prefix"))
&& StringUtils.endsWith(uri, Global.getConfig("web.view.suffix"))){
return;
}
// 手动控制不更新SESSION
String updateSession = request.getParameter("updateSession");
if (Global.FALSE.equals(updateSession) || Global.NO.equals(updateSession)){
return;
}
}
super.doUpdate(session);
logger.debug("update {} {}", session.getId(), request != null ? request.getRequestURI() : "");
}
@Override
protected void doDelete(Session session) {
if (session == null || session.getId() == null) {
return;
}
super.doDelete(session);
logger.debug("delete {} ", session.getId());
}
@Override
protected Serializable doCreate(Session session) {
HttpServletRequest request = Servlets.getRequest();
if (request != null){
String uri = request.getServletPath();
// 如果是静态文件,则不创建SESSION
if (Servlets.isStaticFile(uri)){
return null;
}
}
super.doCreate(session);
logger.debug("doCreate {} {}", session, request != null ? request.getRequestURI() : "");
return session.getId();
}
@Override
protected Session doReadSession(Serializable sessionId) {
return super.doReadSession(sessionId);
}
@Override
public Session readSession(Serializable sessionId) throws UnknownSessionException {
try{
Session s = null;
HttpServletRequest request = Servlets.getRequest();
if (request != null){
String uri = request.getServletPath();
// 如果是静态文件,则不获取SESSION
if (Servlets.isStaticFile(uri)){
return null;
}
s = (Session)request.getAttribute("session_"+sessionId);
}
if (s != null){
return s;
}
Session session = super.readSession(sessionId);
logger.debug("readSession {} {}", sessionId, request != null ? request.getRequestURI() : "");
if (request != null && session != null){
request.setAttribute("session_"+sessionId, session);
}
return session;
}catch (UnknownSessionException e) {
return null;
}
}
/**
* 获取活动会话
* @param includeLeave 是否包括离线(最后访问时间大于3分钟为离线会话)
* @return
*/
@Override
public Collection<Session> getActiveSessions(boolean includeLeave) {
return getActiveSessions(includeLeave, null, null);
}
/**
* 获取活动会话
* @param includeLeave 是否包括离线(最后访问时间大于3分钟为离线会话)
* @param principal 根据登录者对象获取活动会话
* @param filterSession 不为空,则过滤掉(不包含)这个会话。
* @return
*/
@Override
public Collection<Session> getActiveSessions(boolean includeLeave, Object principal, Session filterSession) {
// 如果包括离线,并无登录者条件。
if (includeLeave && principal == null){
return getActiveSessions();
}
Set<Session> sessions = Sets.newHashSet();
for (Session session : getActiveSessions()){
boolean isActiveSession = false;
// 不包括离线并符合最后访问时间小于等于3分钟条件。
if (includeLeave || DateUtils.pastMinutes(session.getLastAccessTime()) <= 3){
isActiveSession = true;
}
// 符合登陆者条件。
if (principal != null){
PrincipalCollection pc = (PrincipalCollection)session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
if (principal.toString().equals(pc != null ? pc.getPrimaryPrincipal().toString() : StringUtils.EMPTY)){
isActiveSession = true;
}
}
// 过滤掉的SESSION
if (filterSession != null && filterSession.getId().equals(session.getId())){
isActiveSession = false;
}
if (isActiveSession){
sessions.add(session);
}
}
return sessions;
}
}