【zheng阅读系列】shiro权限管理

一、配置文件

upms-server/springMVC-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 根目录'/'对应页面 -->
    <mvc:view-controller path="/" view-name="/index.jsp"/>

    <!-- 拦截器 -->
    <mvc:interceptors>
        <!-- 获取登录信息 -->
        <mvc:interceptor>
            <mvc:mapping path="/manage/**"/>
            <bean class="com.zheng.upms.server.interceptor.UpmsInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

    <!-- Jsp视图 -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="order" value="1"/>
        <property name="prefix" value="/WEB-INF/jsp"/>
        <property name="suffix" value=""/>
        <property name="contentType" value="text/html; charset=utf-8"/>
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    </bean>

</beans>

登陆信息拦截器:

 1 package com.zheng.upms.server.interceptor;
 2 
 3 import com.zheng.common.util.PropertiesFileUtil;
 4 import com.zheng.upms.dao.model.UpmsUser;
 5 import com.zheng.upms.rpc.api.UpmsApiService;
 6 import com.zheng.upms.server.controller.manage.UpmsOrganizationController;
 7 import org.apache.shiro.SecurityUtils;
 8 import org.apache.shiro.subject.Subject;
 9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory;
11 import org.springframework.beans.factory.annotation.Autowired;
12 import org.springframework.web.servlet.ModelAndView;
13 import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
14 
15 import javax.servlet.http.HttpServletRequest;
16 import javax.servlet.http.HttpServletResponse;
17 
18 /**
19  * 登录信息拦截器
20  * Created by shuzheng on 2017/2/11.
21  */
22 public class UpmsInterceptor extends HandlerInterceptorAdapter {
23 
24     private static final Logger LOGGER = LoggerFactory.getLogger(UpmsInterceptor.class);
25     private static final String ZHENG_OSS_ALIYUN_OSS_POLICY = PropertiesFileUtil.getInstance("zheng-oss-client").get("zheng.oss.aliyun.oss.policy");
26 
27     @Autowired
28     UpmsApiService upmsApiService;
29 
30     @Override
31     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
32         request.setAttribute("ZHENG_OSS_ALIYUN_OSS_POLICY", ZHENG_OSS_ALIYUN_OSS_POLICY);
33         // 过滤ajax
34         if (null != request.getHeader("X-Requested-With") && "XMLHttpRequest".equalsIgnoreCase(request.getHeader("X-Requested-With"))) {
35             return true;
36         }
37         // 登录信息
38         Subject subject = SecurityUtils.getSubject();
39         String username = (String) subject.getPrincipal();
40         UpmsUser upmsUser = upmsApiService.selectUpmsUserByUsername(username);
41         request.setAttribute("upmsUser", upmsUser);
42         return true;
43     }
44 
45     @Override
46     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
47         super.postHandle(request, response, handler, modelAndView);
48     }
49 
50     @Override
51     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
52         super.afterCompletion(request, response, handler, ex);
53     }
54 
55     @Override
56     public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
57         super.afterConcurrentHandlingStarted(request, response, handler);
58     }
59 
60 }

 

zheng-upms-server:resources/profiles:dev.properties

 1 app.name=zheng-upms-server
 2 profile.env=dev
 3 
 4 ##### redis #####
 5 master.redis.ip=rdserver
 6 master.redis.port=6379
 7 master.redis.password=FNFl9F2O2Skb8yoKM0jhHA==
 8 master.redis.max_active=500
 9 master.redis.max_idle=5
10 master.redis.max_wait=10000
11 master.redis.timeout=10000
12 
13 ##### zheng-admin #####
14 zheng.admin.version=1.0.0
15 
16 ##### zheng-config #####
17 #zheng.config.path=http://config.zhangshuzheng.cn:1000/${app.name}/${profile.env}
18 zheng.config.path=http://127.0.0.1:1000/${app.name}/${profile.env}
19 ##### zheng-upms #####
20 # \u7EC8\u7AEF\u7C7B\u578B
21 zheng.upms.type=server
22 # \u7EC8\u7AEFsession\u540D\u79F0
23 zheng.upms.session.id=zheng-upms-server-session-id
24 # \u4F1A\u8BDD\u65F6\u957F,\u534A\u5C0F\u65F6\uFF08\u5355\u4F4D\u6BEB\u79D2\uFF09
25 zheng.upms.session.timeout=1800000
26 # \u5355\u70B9\u767B\u5F55\u8BA4\u8BC1\u4E2D\u5FC3\u5730\u5740
27 #zheng.upms.sso.server.url=http://upms.zhangshuzheng.cn:1111
28 zheng.upms.sso.server.url=http://127.0.0.1:1111
29 # \u767B\u5F55\u6210\u529F\u56DE\u8C03\u5730\u5740
30 zheng.upms.successUrl=/manage/index
31 # \u672A\u6388\u6743\u5730\u5740
32 zheng.upms.unauthorizedUrl=/403
33 # \u8BB0\u4F4F\u5BC6\u7801\u65F6\u957F30\u5929
34 zheng.upms.rememberMe.timeout=2592000
35 
36 ##### zheng-oss #####
37 #zheng.oss.aliyun.oss.policy=http://oss.zhangshuzheng.cn:7771/aliyun/oss/policy
38 zheng.oss.aliyun.oss.policy=http://127.0.0.1:7771/aliyun/oss/policy

zheng-upms-client:resources/applicationContext-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <description>zheng-upms</description>

    <context:property-placeholder location="classpath*:zheng-upms-client.properties"/>

    <!-- Shiro的Web过滤器 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <property name="loginUrl" value="${zheng.upms.sso.server.url}"/>
        <property name="successUrl" value="${zheng.upms.successUrl}"/>
        <property name="unauthorizedUrl" value="${zheng.upms.unauthorizedUrl}"/>
        <property name="filters">
            <util:map>
                <entry key="authc" value-ref="upmsAuthenticationFilter"/>
            </util:map>
        </property>
        <property name="filterChainDefinitions">
            <value>
                /manage/** = upmsSessionForceLogout,authc
                /manage/index = user
                /druid/** = user
                /swagger-ui.html = user
                /resources/** = anon
                /** = anon
            </value>
        </property>
    </bean>

    <!-- 重写authc过滤器 -->
    <bean id="upmsAuthenticationFilter" class="com.zheng.upms.client.shiro.filter.UpmsAuthenticationFilter"/>

    <!-- 强制退出会话过滤器 -->
    <bean id="upmsSessionForceLogout" class="com.zheng.upms.client.shiro.filter.UpmsSessionForceLogoutFilter"/>

    <!-- 安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realms">
            <list><ref bean="upmsRealm"/></list>
        </property>
        <property name="sessionManager" ref="sessionManager"/>
        <property name="rememberMeManager" ref="rememberMeManager"/>
    </bean>

    <!-- realm实现,继承自AuthorizingRealm -->
    <bean id="upmsRealm" class="com.zheng.upms.client.shiro.realm.UpmsRealm"></bean>

    <!-- 会话管理器 -->
    <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
        <!-- 全局session超时时间 -->
        <property name="globalSessionTimeout" value="${zheng.upms.session.timeout}"/>
        <!-- sessionDAO -->
        <property name="sessionDAO" ref="sessionDAO"/>
        <property name="sessionIdCookieEnabled" value="true"/>
        <property name="sessionIdCookie" ref="sessionIdCookie"/>
        <property name="sessionValidationSchedulerEnabled" value="false"/>
        <property name="sessionListeners">
            <list><ref bean="sessionListener"/></list>
        </property>
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <!-- 会话DAO,可重写,持久化session -->
    <bean id="sessionDAO" class="com.zheng.upms.client.shiro.session.UpmsSessionDao"/>

    <!-- 会话Cookie模板 -->
    <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <!-- 不会暴露给客户端 -->
        <property name="httpOnly" value="true"/>
        <!-- 设置Cookie的过期时间,秒为单位,默认-1表示关闭浏览器时过期Cookie -->
        <property name="maxAge" value="-1"/>
        <!-- Cookie名称 -->
        <property name="name" value="${zheng.upms.session.id}"/>
    </bean>

    <!-- 会话监听器 -->
    <bean id="sessionListener" class="com.zheng.upms.client.shiro.listener.UpmsSessionListener"/>

    <!-- session工厂 -->
    <bean id="sessionFactory" class="com.zheng.upms.client.shiro.session.UpmsSessionFactory"/>

    <!-- rememberMe管理器 -->
    <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
        <!-- rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)-->
        <property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}"/>
        <property name="cookie" ref="rememberMeCookie"/>
    </bean>

    <!-- rememberMe缓存cookie -->
    <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <constructor-arg value="rememberMe"/>
        <!-- 不会暴露给客户端 -->
        <property name="httpOnly" value="true"/>
        <!-- 记住我cookie生效时间 -->
        <property name="maxAge" value="${zheng.upms.rememberMe.timeout}"/>
    </bean>

    <!-- 设置SecurityUtils,相当于调用SecurityUtils.setSecurityManager(securityManager) -->
    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
        <property name="arguments" ref="securityManager"/>
    </bean>

    <!-- 开启Shiro Spring AOP权限注解@RequiresPermissions的支持 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/>
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>

    <!-- Shiro生命周期处理器-->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

</beans>

authc过滤器:

  1 package com.zheng.upms.client.shiro.filter;
  2 
  3 import com.alibaba.fastjson.JSONObject;
  4 import com.zheng.common.util.PropertiesFileUtil;
  5 import com.zheng.common.util.RedisUtil;
  6 import com.zheng.upms.client.shiro.session.UpmsSessionDao;
  7 import com.zheng.upms.client.util.RequestParameterUtil;
  8 import com.zheng.upms.common.constant.UpmsConstant;
  9 import org.apache.commons.lang.StringUtils;
 10 import org.apache.http.HttpEntity;
 11 import org.apache.http.HttpResponse;
 12 import org.apache.http.HttpStatus;
 13 import org.apache.http.NameValuePair;
 14 import org.apache.http.client.HttpClient;
 15 import org.apache.http.client.entity.UrlEncodedFormEntity;
 16 import org.apache.http.client.methods.HttpPost;
 17 import org.apache.http.impl.client.DefaultHttpClient;
 18 import org.apache.http.message.BasicNameValuePair;
 19 import org.apache.http.util.EntityUtils;
 20 import org.apache.shiro.authc.UsernamePasswordToken;
 21 import org.apache.shiro.session.Session;
 22 import org.apache.shiro.subject.Subject;
 23 import org.apache.shiro.web.filter.authc.AuthenticationFilter;
 24 import org.apache.shiro.web.util.WebUtils;
 25 import org.slf4j.Logger;
 26 import org.slf4j.LoggerFactory;
 27 import org.springframework.beans.factory.annotation.Autowired;
 28 import redis.clients.jedis.Jedis;
 29 
 30 import javax.servlet.ServletRequest;
 31 import javax.servlet.ServletResponse;
 32 import javax.servlet.http.HttpServletRequest;
 33 import javax.servlet.http.HttpServletResponse;
 34 import java.io.IOException;
 35 import java.net.URLEncoder;
 36 import java.util.ArrayList;
 37 import java.util.List;
 38 
 39 /**
 40  * 重写authc过滤器
 41  * Created by shuzheng on 2017/3/11.
 42  */
 43 public class UpmsAuthenticationFilter extends AuthenticationFilter {
 44 
 45     private static final Logger LOGGER = LoggerFactory.getLogger(UpmsAuthenticationFilter.class);
 46 
 47     // 局部会话key
 48     private final static String ZHENG_UPMS_CLIENT_SESSION_ID = "zheng-upms-client-session-id";
 49     // 单点同一个code所有局部会话key
 50     private final static String ZHENG_UPMS_CLIENT_SESSION_IDS = "zheng-upms-client-session-ids";
 51 
 52     @Autowired
 53     UpmsSessionDao upmsSessionDao;
 54 
 55     @Override
 56     protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
 57         Subject subject = getSubject(request, response);
 58         Session session = subject.getSession();
 59         // 判断请求类型
 60         String upmsType = PropertiesFileUtil.getInstance("zheng-upms-client").get("zheng.upms.type");
 61         session.setAttribute(UpmsConstant.UPMS_TYPE, upmsType);
 62         if ("client".equals(upmsType)) {
 63             return validateClient(request, response);
 64         }
 65         if ("server".equals(upmsType)) {
 66             return subject.isAuthenticated();
 67         }
 68         return false;
 69     }
 70 
 71     @Override
 72     protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
 73         StringBuffer ssoServerUrl = new StringBuffer(PropertiesFileUtil.getInstance("zheng-upms-client").get("zheng.upms.sso.server.url"));
 74         // server需要登录
 75         String upmsType = PropertiesFileUtil.getInstance("zheng-upms-client").get("zheng.upms.type");
 76         if ("server".equals(upmsType)) {
 77             WebUtils.toHttp(response).sendRedirect(ssoServerUrl.append("/sso/login").toString());
 78             return false;
 79         }
 80         ssoServerUrl.append("/sso/index").append("?").append("appid").append("=").append(PropertiesFileUtil.getInstance("zheng-upms-client").get("zheng.upms.appID"));
 81         // 回跳地址
 82         HttpServletRequest httpServletRequest = WebUtils.toHttp(request);
 83         StringBuffer backurl = httpServletRequest.getRequestURL();
 84         String queryString = httpServletRequest.getQueryString();
 85         if (StringUtils.isNotBlank(queryString)) {
 86             backurl.append("?").append(queryString);
 87         }
 88         ssoServerUrl.append("&").append("backurl").append("=").append(URLEncoder.encode(backurl.toString(), "utf-8"));
 89         WebUtils.toHttp(response).sendRedirect(ssoServerUrl.toString());
 90         return false;
 91     }
 92 
 93     /**
 94      * 认证中心登录成功带回code
 95      * @param request
 96      */
 97     private boolean validateClient(ServletRequest request, ServletResponse response) {
 98         Subject subject = getSubject(request, response);
 99         Session session = subject.getSession();
100         String sessionId = session.getId().toString();
101         int timeOut = (int) session.getTimeout() / 1000;
102         // 判断局部会话是否登录
103         String cacheClientSession = RedisUtil.get(ZHENG_UPMS_CLIENT_SESSION_ID + "_" + session.getId());
104         if (StringUtils.isNotBlank(cacheClientSession)) {
105             // 更新code有效期
106             RedisUtil.set(ZHENG_UPMS_CLIENT_SESSION_ID + "_" + sessionId, cacheClientSession, timeOut);
107             Jedis jedis = RedisUtil.getJedis();
108             jedis.expire(ZHENG_UPMS_CLIENT_SESSION_IDS + "_" + cacheClientSession, timeOut);
109             jedis.close();
110             // 移除url中的code参数
111             if (null != request.getParameter("code")) {
112                 String backUrl = RequestParameterUtil.getParameterWithOutCode(WebUtils.toHttp(request));
113                 HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
114                 try {
115                     httpServletResponse.sendRedirect(backUrl.toString());
116                 } catch (IOException e) {
117                     LOGGER.error("局部会话已登录,移除code参数跳转出错:", e);
118                 }
119             } else {
120                 return true;
121             }
122         }
123         // 判断是否有认证中心code
124         String code = request.getParameter("upms_code");
125         // 已拿到code
126         if (StringUtils.isNotBlank(code)) {
127             // HttpPost去校验code
128             try {
129                 StringBuffer ssoServerUrl = new StringBuffer(PropertiesFileUtil.getInstance("zheng-upms-client").get("zheng.upms.sso.server.url"));
130                 HttpClient httpclient = new DefaultHttpClient();
131                 HttpPost httpPost = new HttpPost(ssoServerUrl.toString() + "/sso/code");
132 
133                 List<NameValuePair> nameValuePairs = new ArrayList<>();
134                 nameValuePairs.add(new BasicNameValuePair("code", code));
135                 httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
136 
137                 HttpResponse httpResponse = httpclient.execute(httpPost);
138                 if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
139                     HttpEntity httpEntity = httpResponse.getEntity();
140                     JSONObject result = JSONObject.parseObject(EntityUtils.toString(httpEntity));
141                     if (1 == result.getIntValue("code") && result.getString("data").equals(code)) {
142                         // code校验正确,创建局部会话
143                         RedisUtil.set(ZHENG_UPMS_CLIENT_SESSION_ID + "_" + sessionId, code, timeOut);
144                         // 保存code对应的局部会话sessionId,方便退出操作
145                         RedisUtil.sadd(ZHENG_UPMS_CLIENT_SESSION_IDS + "_" + code, sessionId, timeOut);
146                         LOGGER.debug("当前code={},对应的注册系统个数:{}个", code, RedisUtil.getJedis().scard(ZHENG_UPMS_CLIENT_SESSION_IDS + "_" + code));
147                         // 移除url中的token参数
148                         String backUrl = RequestParameterUtil.getParameterWithOutCode(WebUtils.toHttp(request));
149                         // 返回请求资源
150                         try {
151                             // client无密认证
152                             String username = request.getParameter("upms_username");
153                             subject.login(new UsernamePasswordToken(username, ""));
154                             HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
155                             httpServletResponse.sendRedirect(backUrl.toString());
156                             return true;
157                         } catch (IOException e) {
158                             LOGGER.error("已拿到code,移除code参数跳转出错:", e);
159                         }
160                     } else {
161                         LOGGER.warn(result.getString("data"));
162                     }
163                 }
164             } catch (IOException e) {
165                 LOGGER.error("验证token失败:", e);
166             }
167         }
168         return false;
169     }
170 
171 }

强制退出会话过滤器:

 1 package com.zheng.upms.client.shiro.filter;
 2 
 3 import org.apache.shiro.session.Session;
 4 import org.apache.shiro.web.filter.AccessControlFilter;
 5 import org.apache.shiro.web.util.WebUtils;
 6 
 7 import javax.servlet.ServletRequest;
 8 import javax.servlet.ServletResponse;
 9 
10 /**
11  * 强制退出会话过滤器
12  * Created by shuzheng on 2017/3/1.
13  */
14 public class UpmsSessionForceLogoutFilter extends AccessControlFilter {
15 
16     @Override
17     protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
18         Session session = getSubject(request, response).getSession(false);
19         if(session == null) {
20             return true;
21         }
22         boolean forceout = session.getAttribute("FORCE_LOGOUT") == null;
23         return  forceout;
24     }
25 
26     @Override
27     protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
28         getSubject(request, response).logout();
29         String loginUrl = getLoginUrl() + (getLoginUrl().contains("?") ? "&" : "?") + "forceLogout=1";
30         WebUtils.issueRedirect(request, response, loginUrl);
31         return false;
32     }
33 
34 }

realm自定义实现:

  1 package com.zheng.upms.client.shiro.realm;
  2 
  3 import com.zheng.common.util.MD5Util;
  4 import com.zheng.common.util.PropertiesFileUtil;
  5 import com.zheng.upms.dao.model.UpmsPermission;
  6 import com.zheng.upms.dao.model.UpmsRole;
  7 import com.zheng.upms.dao.model.UpmsUser;
  8 import com.zheng.upms.rpc.api.UpmsApiService;
  9 import org.apache.commons.lang.StringUtils;
 10 import org.apache.shiro.authc.*;
 11 import org.apache.shiro.authz.AuthorizationInfo;
 12 import org.apache.shiro.authz.SimpleAuthorizationInfo;
 13 import org.apache.shiro.realm.AuthorizingRealm;
 14 import org.apache.shiro.subject.PrincipalCollection;
 15 import org.slf4j.Logger;
 16 import org.slf4j.LoggerFactory;
 17 import org.springframework.beans.factory.annotation.Autowired;
 18 
 19 import java.util.HashSet;
 20 import java.util.List;
 21 import java.util.Set;
 22 
 23 /**
 24  * 用户认证和授权
 25  * Created by shuzheng on 2017/1/20.
 26  */
 27 public class UpmsRealm extends AuthorizingRealm {
 28 
 29     private static final Logger LOGGER = LoggerFactory.getLogger(UpmsRealm.class);
 30 
 31     @Autowired
 32     private UpmsApiService upmsApiService;
 33 
 34     /**
 35      * 授权:验证权限时调用
 36      * @param principalCollection
 37      * @return
 38      */
 39     @Override
 40     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
 41         String username = (String) principalCollection.getPrimaryPrincipal();
 42         UpmsUser upmsUser = upmsApiService.selectUpmsUserByUsername(username);
 43 
 44         // 当前用户所有角色
 45         List<UpmsRole> upmsRoles = upmsApiService.selectUpmsRoleByUpmsUserId(upmsUser.getUserId());
 46         Set<String> roles = new HashSet<>();
 47         for (UpmsRole upmsRole : upmsRoles) {
 48             if (StringUtils.isNotBlank(upmsRole.getName())) {
 49                 roles.add(upmsRole.getName());
 50             }
 51         }
 52 
 53         // 当前用户所有权限
 54         List<UpmsPermission> upmsPermissions = upmsApiService.selectUpmsPermissionByUpmsUserId(upmsUser.getUserId());
 55         Set<String> permissions = new HashSet<>();
 56         for (UpmsPermission upmsPermission : upmsPermissions) {
 57             if (StringUtils.isNotBlank(upmsPermission.getPermissionValue())) {
 58                 permissions.add(upmsPermission.getPermissionValue());
 59             }
 60         }
 61 
 62         SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
 63         simpleAuthorizationInfo.setStringPermissions(permissions);
 64         simpleAuthorizationInfo.setRoles(roles);
 65         return simpleAuthorizationInfo;
 66     }
 67 
 68     /**
 69      * 认证:登录时调用
 70      * @param authenticationToken
 71      * @return
 72      * @throws AuthenticationException
 73      */
 74     @Override
 75     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
 76         String username = (String) authenticationToken.getPrincipal();
 77         String password = new String((char[]) authenticationToken.getCredentials());
 78         // client无密认证
 79         String upmsType = PropertiesFileUtil.getInstance("zheng-upms-client").get("zheng.upms.type");
 80         if ("client".equals(upmsType)) {
 81             return new SimpleAuthenticationInfo(username, password, getName());
 82         }
 83 
 84         // 查询用户信息
 85         UpmsUser upmsUser = upmsApiService.selectUpmsUserByUsername(username);
 86 
 87         if (null == upmsUser) {
 88             throw new UnknownAccountException();
 89         }
 90         if (!upmsUser.getPassword().equals(MD5Util.md5(password + upmsUser.getSalt()))) {
 91             throw new IncorrectCredentialsException();
 92         }
 93         if (upmsUser.getLocked() == 1) {
 94             throw new LockedAccountException();
 95         }
 96 
 97         return new SimpleAuthenticationInfo(username, password, getName());
 98     }
 99 
100 }

会话DAO:

  1 package com.zheng.upms.client.shiro.session;
  2 
  3 import com.zheng.common.util.RedisUtil;
  4 import com.zheng.upms.client.util.SerializableUtil;
  5 import com.zheng.upms.common.constant.UpmsConstant;
  6 import org.apache.commons.lang.ObjectUtils;
  7 import org.apache.shiro.session.Session;
  8 import org.apache.shiro.session.mgt.ValidatingSession;
  9 import org.apache.shiro.session.mgt.eis.CachingSessionDAO;
 10 import org.slf4j.Logger;
 11 import org.slf4j.LoggerFactory;
 12 import redis.clients.jedis.Jedis;
 13 
 14 import java.io.Serializable;
 15 import java.util.*;
 16 
 17 /**
 18  * 基于redis的sessionDao,缓存共享session
 19  * Created by shuzheng on 2017/2/23.
 20  */
 21 public class UpmsSessionDao extends CachingSessionDAO {
 22 
 23     private static final Logger LOGGER = LoggerFactory.getLogger(UpmsSessionDao.class);
 24     // 会话key
 25     private final static String ZHENG_UPMS_SHIRO_SESSION_ID = "zheng-upms-shiro-session-id";
 26     // 全局会话key
 27     private final static String ZHENG_UPMS_SERVER_SESSION_ID = "zheng-upms-server-session-id";
 28     // 全局会话列表key
 29     private final static String ZHENG_UPMS_SERVER_SESSION_IDS = "zheng-upms-server-session-ids";
 30     // code key
 31     private final static String ZHENG_UPMS_SERVER_CODE = "zheng-upms-server-code";
 32     // 局部会话key
 33     private final static String ZHENG_UPMS_CLIENT_SESSION_ID = "zheng-upms-client-session-id";
 34     // 单点同一个code所有局部会话key
 35     private final static String ZHENG_UPMS_CLIENT_SESSION_IDS = "zheng-upms-client-session-ids";
 36 
 37     @Override
 38     protected Serializable doCreate(Session session) {
 39         Serializable sessionId = generateSessionId(session);
 40         assignSessionId(session, sessionId);
 41         RedisUtil.set(ZHENG_UPMS_SHIRO_SESSION_ID + "_" + sessionId, SerializableUtil.serialize(session), (int) session.getTimeout() / 1000);
 42         LOGGER.debug("doCreate >>>>> sessionId={}", sessionId);
 43         return sessionId;
 44     }
 45 
 46     @Override
 47     protected Session doReadSession(Serializable sessionId) {
 48         String session = RedisUtil.get(ZHENG_UPMS_SHIRO_SESSION_ID + "_" + sessionId);
 49         LOGGER.debug("doReadSession >>>>> sessionId={}", sessionId);
 50         return SerializableUtil.deserialize(session);
 51     }
 52 
 53     @Override
 54     protected void doUpdate(Session session) {
 55         // 如果会话过期/停止 没必要再更新了
 56         if(session instanceof ValidatingSession && !((ValidatingSession)session).isValid()) {
 57             return;
 58         }
 59         // 更新session的最后一次访问时间
 60         UpmsSession upmsSession = (UpmsSession) session;
 61         UpmsSession cacheUpmsSession = (UpmsSession) doReadSession(session.getId());
 62         if (null != cacheUpmsSession) {
 63             upmsSession.setStatus(cacheUpmsSession.getStatus());
 64             upmsSession.setAttribute("FORCE_LOGOUT", cacheUpmsSession.getAttribute("FORCE_LOGOUT"));
 65         }
 66         RedisUtil.set(ZHENG_UPMS_SHIRO_SESSION_ID + "_" + session.getId(), SerializableUtil.serialize(session), (int) session.getTimeout() / 1000);
 67         // 更新ZHENG_UPMS_SERVER_SESSION_ID、ZHENG_UPMS_SERVER_CODE过期时间 TODO
 68         LOGGER.debug("doUpdate >>>>> sessionId={}", session.getId());
 69     }
 70 
 71     @Override
 72     protected void doDelete(Session session) {
 73         String sessionId = session.getId().toString();
 74         String upmsType = ObjectUtils.toString(session.getAttribute(UpmsConstant.UPMS_TYPE));
 75         if ("client".equals(upmsType)) {
 76             // 删除局部会话和同一code注册的局部会话
 77             String code = RedisUtil.get(ZHENG_UPMS_CLIENT_SESSION_ID + "_" + sessionId);
 78             Jedis jedis = RedisUtil.getJedis();
 79             jedis.del(ZHENG_UPMS_CLIENT_SESSION_ID + "_" + sessionId);
 80             jedis.srem(ZHENG_UPMS_CLIENT_SESSION_IDS + "_" + code, sessionId);
 81             jedis.close();
 82         }
 83         if ("server".equals(upmsType)) {
 84             // 当前全局会话code
 85             String code = RedisUtil.get(ZHENG_UPMS_SERVER_SESSION_ID + "_" + sessionId);
 86             // 清除全局会话
 87             RedisUtil.remove(ZHENG_UPMS_SERVER_SESSION_ID + "_" + sessionId);
 88             // 清除code校验值
 89             RedisUtil.remove(ZHENG_UPMS_SERVER_CODE + "_" + code);
 90             // 清除所有局部会话
 91             Jedis jedis = RedisUtil.getJedis();
 92             Set<String> clientSessionIds = jedis.smembers(ZHENG_UPMS_CLIENT_SESSION_IDS + "_" + code);
 93             for (String clientSessionId : clientSessionIds) {
 94                 jedis.del(ZHENG_UPMS_CLIENT_SESSION_ID + "_" + clientSessionId);
 95                 jedis.srem(ZHENG_UPMS_CLIENT_SESSION_IDS + "_" + code, clientSessionId);
 96             }
 97             LOGGER.debug("当前code={},对应的注册系统个数:{}个", code, jedis.scard(ZHENG_UPMS_CLIENT_SESSION_IDS + "_" + code));
 98             jedis.close();
 99             // 维护会话id列表,提供会话分页管理
100             RedisUtil.lrem(ZHENG_UPMS_SERVER_SESSION_IDS, 1, sessionId);
101         }
102         // 删除session
103         RedisUtil.remove(ZHENG_UPMS_SHIRO_SESSION_ID + "_" + sessionId);
104         LOGGER.debug("doUpdate >>>>> sessionId={}", sessionId);
105     }
106 
107     /**
108      * 获取会话列表
109      * @param offset
110      * @param limit
111      * @return
112      */
113     public Map getActiveSessions(int offset, int limit) {
114         LOGGER.info("进入getActiveSession获取当前活动的session数据,服务端分页需要返回total 和rows");
115         Map sessions = new HashMap();
116         Jedis jedis = RedisUtil.getJedis();
117         // 获取在线会话总数
118         long total = jedis.llen(ZHENG_UPMS_SERVER_SESSION_IDS);
119         // 获取当前页会话详情
120         List<String> ids = jedis.lrange(ZHENG_UPMS_SERVER_SESSION_IDS, offset, (offset + limit - 1));
121         List<Session> rows = new ArrayList<>();
122         for (String id : ids) {
123             String session = RedisUtil.get(ZHENG_UPMS_SHIRO_SESSION_ID + "_" + id);
124             // 过滤redis过期session
125             if (null == session) {
126                 RedisUtil.lrem(ZHENG_UPMS_SERVER_SESSION_IDS, 1, id);
127                 total = total - 1;
128                 continue;
129             }
130              rows.add(SerializableUtil.deserialize(session));
131         }
132         jedis.close();
133         sessions.put("total", total);
134         sessions.put("rows", rows);
135         return sessions;
136     }
137 
138     /**
139      * 强制退出
140      * @param ids
141      * @return
142      */
143     public int forceout(String ids) {
144         String[] sessionIds = ids.split(",");
145         for (String sessionId : sessionIds) {
146             // 会话增加强制退出属性标识,当此会话访问系统时,判断有该标识,则退出登录
147             String session = RedisUtil.get(ZHENG_UPMS_SHIRO_SESSION_ID + "_" + sessionId);
148             UpmsSession upmsSession = (UpmsSession) SerializableUtil.deserialize(session);
149             upmsSession.setStatus(UpmsSession.OnlineStatus.force_logout);
150             upmsSession.setAttribute("FORCE_LOGOUT", "FORCE_LOGOUT");
151             RedisUtil.set(ZHENG_UPMS_SHIRO_SESSION_ID + "_" + sessionId, SerializableUtil.serialize(upmsSession), (int) upmsSession.getTimeout() / 1000);
152         }
153         return sessionIds.length;
154     }
155 
156     /**
157      * 更改在线状态
158      *
159      * @param sessionId
160      * @param onlineStatus
161      */
162     public void updateStatus(Serializable sessionId, UpmsSession.OnlineStatus onlineStatus) {
163         UpmsSession session = (UpmsSession) doReadSession(sessionId);
164         if (null == session) {
165             return;
166         }
167         session.setStatus(onlineStatus);
168         RedisUtil.set(ZHENG_UPMS_SHIRO_SESSION_ID + "_" + session.getId(), SerializableUtil.serialize(session), (int) session.getTimeout() / 1000);
169     }
170 
171 }

会话监听器:

package com.zheng.upms.client.shiro.listener;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.SessionListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by shuzheng on 2017/2/12.
 */
public class UpmsSessionListener implements SessionListener {

    private static final Logger LOGGER = LoggerFactory.getLogger(UpmsSessionListener.class);

    @Override
    public void onStart(Session session) {
        LOGGER.debug("会话创建:" + session.getId());
    }

    @Override
    public void onStop(Session session) {
        LOGGER.debug("会话停止:" + session.getId());
    }

    @Override
    public void onExpiration(Session session) {
        LOGGER.debug("会话过期:" + session.getId());
    }

}

会话工厂:

 1 package com.zheng.upms.client.shiro.session;
 2 
 3 import org.apache.shiro.session.Session;
 4 import org.apache.shiro.session.mgt.SessionContext;
 5 import org.apache.shiro.session.mgt.SessionFactory;
 6 import org.apache.shiro.web.session.mgt.WebSessionContext;
 7 
 8 import javax.servlet.http.HttpServletRequest;
 9 
10 /**
11  * session工厂
12  * Created by shuzheng on 2017/2/27.
13  */
14 public class UpmsSessionFactory implements SessionFactory {
15 
16     @Override
17     public Session createSession(SessionContext sessionContext) {
18         UpmsSession session = new UpmsSession();
19         if (null != sessionContext && sessionContext instanceof WebSessionContext) {
20             WebSessionContext webSessionContext = (WebSessionContext) sessionContext;
21             HttpServletRequest request = (HttpServletRequest) webSessionContext.getServletRequest();
22             if (null != request) {
23                 session.setHost(request.getRemoteAddr());
24                 session.setUserAgent(request.getHeader("User-Agent"));
25             }
26         }
27         return session;
28     }
29 
30 }

二、日志记录切面

springMVC-servlet.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        xmlns:aop="http://www.springframework.org/schema/aop"
 5        xsi:schemaLocation="http://www.springframework.org/schema/beans
 6        http://www.springframework.org/schema/beans/spring-beans.xsd
 7        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
 8

       通过配置织入@Aspectj切面

 9     <aop:aspectj-autoproxy proxy-target-class="true"/>
10 
11     <!-- 日志记录AOP实现 -->
12     <bean class="com.zheng.upms.client.interceptor.LogAspect"/>
13 
14 
15     <!-- 日志记录AOP实现 -->
16     <bean class="com.zheng.common.aspect.RpcLogAspect"/>
17 
18 </beans>

LogAspect实现:

  1 package com.zheng.upms.client.interceptor;
  2 
  3 import com.alibaba.fastjson.JSON;
  4 import com.zheng.common.util.RequestUtil;
  5 import com.zheng.upms.dao.model.UpmsLog;
  6 import com.zheng.upms.rpc.api.UpmsApiService;
  7 import io.swagger.annotations.ApiOperation;
  8 import org.apache.commons.lang.ObjectUtils;
  9 import org.apache.shiro.authz.annotation.RequiresPermissions;
 10 import org.aspectj.lang.JoinPoint;
 11 import org.aspectj.lang.ProceedingJoinPoint;
 12 import org.aspectj.lang.Signature;
 13 import org.aspectj.lang.annotation.After;
 14 import org.aspectj.lang.annotation.Around;
 15 import org.aspectj.lang.annotation.Aspect;
 16 import org.aspectj.lang.annotation.Before;
 17 import org.aspectj.lang.reflect.MethodSignature;
 18 import org.slf4j.Logger;
 19 import org.slf4j.LoggerFactory;
 20 import org.springframework.beans.factory.annotation.Autowired;
 21 import org.springframework.web.context.request.RequestAttributes;
 22 import org.springframework.web.context.request.RequestContextHolder;
 23 import org.springframework.web.context.request.ServletRequestAttributes;
 24 
 25 import javax.servlet.http.HttpServletRequest;
 26 import java.lang.reflect.Method;
 27 
 28 /**
 29  * 日志记录AOP实现
 30  * Created by ZhangShuzheng on 2017/3/14.
 31  */
 32 @Aspect
 33 public class LogAspect {
 34 
 35     private static final Logger LOGGER = LoggerFactory.getLogger(LogAspect.class);
 36 
 37     // 开始时间
 38     private long startTime = 0L;
 39     // 结束时间
 40     private long endTime = 0L;
 41 
 42     @Autowired
 43     UpmsApiService upmsApiService;
 44 
 45     @Before("execution(* *..controller..*.*(..))")
 46     public void doBeforeInServiceLayer(JoinPoint joinPoint) {
 47         LOGGER.debug("doBeforeInServiceLayer");
 48         startTime = System.currentTimeMillis();
 49     }
 50 
 51     @After("execution(* *..controller..*.*(..))")
 52     public void doAfterInServiceLayer(JoinPoint joinPoint) {
 53         LOGGER.debug("doAfterInServiceLayer");
 54     }
 55 
 56     @Around("execution(* *..controller..*.*(..))")
 57     public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
 58         // 获取request
 59         RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
 60         ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
 61         HttpServletRequest request = servletRequestAttributes.getRequest();
 62 
 63         UpmsLog upmsLog = new UpmsLog();
 64         // 从注解中获取操作名称、获取响应结果
 65         Object result = pjp.proceed();
 66         Signature signature = pjp.getSignature();
 67         MethodSignature methodSignature = (MethodSignature) signature;
 68         Method method = methodSignature.getMethod();
 69         if (method.isAnnotationPresent(ApiOperation.class)) {
 70             ApiOperation log = method.getAnnotation(ApiOperation.class);
 71             upmsLog.setDescription(log.value());
 72         }
 73         if (method.isAnnotationPresent(RequiresPermissions.class)) {
 74             RequiresPermissions requiresPermissions = method.getAnnotation(RequiresPermissions.class);
 75             String[] permissions = requiresPermissions.value();
 76             if (permissions.length > 0) {
 77                 upmsLog.setPermissions(permissions[0]);
 78             }
 79         }
 80         endTime = System.currentTimeMillis();
 81         LOGGER.debug("doAround>>>result={},耗时:{}", result, endTime - startTime);
 82 
 83         upmsLog.setBasePath(RequestUtil.getBasePath(request));
 84         upmsLog.setIp(RequestUtil.getIpAddr(request));
 85         upmsLog.setMethod(request.getMethod());
 86         if ("GET".equalsIgnoreCase(request.getMethod())) {
 87             upmsLog.setParameter(request.getQueryString());
 88         } else {
 89             upmsLog.setParameter(ObjectUtils.toString(request.getParameterMap()));
 90         }
 91         upmsLog.setResult(JSON.toJSONString(result));
 92         upmsLog.setSpendTime((int) (endTime - startTime));
 93         upmsLog.setStartTime(startTime);
 94         upmsLog.setUri(request.getRequestURI());
 95         upmsLog.setUrl(ObjectUtils.toString(request.getRequestURL()));
 96         upmsLog.setUserAgent(request.getHeader("User-Agent"));
 97         upmsLog.setUsername(ObjectUtils.toString(request.getUserPrincipal()));
 98         upmsApiService.insertUpmsLogSelective(upmsLog);
 99         return result;
100     }
101 
102 }

rpc消费日志记录:

package com.zheng.common.aspect;

import com.alibaba.dubbo.rpc.RpcContext;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * rpc提供者和消费者日志打印
 * Created by ZhangShuzheng on 2017/4/19.
 */
public class RpcLogAspect {

	private static final Logger LOGGER = LoggerFactory.getLogger(RpcLogAspect.class);

	// 开始时间
	private long startTime = 0L;
	// 结束时间
	private long endTime = 0L;

	@Before("execution(* *..rpc..*.*(..))")
	public void doBeforeInServiceLayer(JoinPoint joinPoint) {
		LOGGER.debug("doBeforeInServiceLayer");
		startTime = System.currentTimeMillis();
	}

	@After("execution(* *..rpc..*.*(..))")
	public void doAfterInServiceLayer(JoinPoint joinPoint) {
		LOGGER.debug("doAfterInServiceLayer");
	}

	@Around("execution(* *..rpc..*.*(..))")
	public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
		Object result = pjp.proceed();
		// 是否是消费端
		boolean consumerSide = RpcContext.getContext().isConsumerSide();
		// 获取最后一次提供方或调用方IP
		String ip = RpcContext.getContext().getRemoteHost();
		// 服务url
		String rpcUrl = RpcContext.getContext().getUrl().getParameter("application");
		LOGGER.info("consumerSide={}, ip={}, url={}", consumerSide, ip, rpcUrl);
		return result;
	}

}

  

二、session管理页面

  1 <%@ page contentType="text/html; charset=utf-8"%>
  2 <%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c"%>
  3 <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
  4 <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
  5 <%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
  6 <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
  7 <%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
  8 <c:set var="basePath" value="${pageContext.request.contextPath}"/>
  9 <!DOCTYPE HTML>
 10 <html lang="zh-cn">
 11 <head>
 12     <meta charset="utf-8">
 13     <meta http-equiv="X-UA-Compatible" content="IE=edge">
 14     <meta name="viewport" content="width=device-width, initial-scale=1">
 15     <title>会话管理</title>
 16     <jsp:include page="/resources/inc/head.jsp" flush="true"/>
 17 </head>
 18 <body>
 19 <div id="main">
 20     <div id="toolbar">
 21         <shiro:hasPermission name="upms:session:forceout"><a class="waves-effect waves-button" href="javascript:;" οnclick="forceoutAction()"><i class="zmdi zmdi-run"></i> 强制退出</a></shiro:hasPermission>
 22     </div>
 23     <table id="table"></table>
 24 </div>
 25 <jsp:include page="/resources/inc/footer.jsp" flush="true"/>
 26 <script>
 27 var $table = $('#table');
 28 $(function() {
 29     // bootstrap table初始化
 30     $table.bootstrapTable({
 31         //向服务器请求的url。
 32         url: '${basePath}/manage/session/list',
 33         //表格的高度
 34         height: getHeight(),
 35         //默认false,当设为true,则每行表格的背景会显示灰白相间
 36         striped: true,
 37         //默认false不显示表格右上方搜索框 ,可设为true,在搜索框内只要输入内容即开始搜索
 38         search: false,
 39         //默认为false隐藏刷新按钮,设为true显示
 40         showRefresh: true,
 41         //默认为false隐藏某列下拉菜单,设为true显示
 42         showColumns: true,
 43         //每列的下拉菜单最小数
 44         minimumCountColumns: 2,
 45         //默认false不响应,设为true则当点击此行的某处时,会自动选中此行的checkbox(复选框)或radiobox(单选按钮)
 46         clickToSelect: true,
 47         //默认false,设为true显示detail view(细节视图)
 48         detailView: true,
 49         //前提:detailView设为true,启用了显示detail view。
 50         // 用于格式化细节视图
 51         // 返回一个字符串,通过第三个参数element直接添加到细节视图的cell(某一格)中,其中,element为目标cell的jQuery element
 52         detailFormatter: 'detailFormatter',
 53         //默认为false,表格的底部工具栏不会显示分页条(pagination toolbar),可以设为true来显示
 54         pagination: true,
 55         //默认true,分页条无限循环
 56         paginationLoop: false,
 57         //设置在哪进行分页,默认”client”,可选”server”,如果设置 “server”,则必须设置url或者重写ajax方法
 58         sidePagination: 'server',
 59         //设置为 false 将在点击分页按钮时,自动记住排序项。仅在 sidePagination设置为 server时生效。
 60         silentSort: false,
 61         //设置为 true 是程序自动判断显示分页信息和 card 视图。
 62         smartDisplay: false,
 63         //转义HTML字符串,替换 &, <, >, ", \`, 和 ' 字符。
 64         escape: true,
 65         //设置为 true时,按回车触发搜索方法,否则自动触发搜索方法。
 66         searchOnEnterKey: true,
 67         //指定主键列。
 68         idField: 'id',
 69         //设置为 true 在点击分页按钮或搜索按钮时,将记住checkbox的选择项。\
 70         maintainSelected: true,
 71         //一个jQuery 选择器,指明自定义的 toolbar。例如:#toolbar, .toolbar.
 72         toolbar: '#toolbar',
 73         //列配置项,详情请查看 列参数 表格.
 74         columns: [
 75             {field: 'ck', checkbox: true},
 76             {field: 'id', title: '编号', sortable: true, align: 'center'},
 77             {field: 'startTimestamp', title: '创建时间', sortable: true, align: 'center'},
 78             {field: 'lastAccessTime', title: '最后访问时间'},
 79             {field: 'expired', title: '是否过期', align: 'center'},
 80             {field: 'host', title: '访问者IP', align: 'center'},
 81             {field: 'userAgent', title: '用户标识', align: 'center'},
 82             {field: 'status', title: '状态', align: 'center', formatter: 'statusFormatter'}
 83         ]
 84     });
 85 });
 86 // 格式化状态
 87 function statusFormatter(value, row, index) {
 88     if (value == 'on_line') {
 89         return '<span class="label label-success">在线</span>';
 90     }
 91     if (value == 'off_line') {
 92         return '<span class="label label-default">离线</span>';
 93     }
 94     if (value == 'force_logout') {
 95         return '<span class="label label-danger">踢离</span>';
 96     }
 97 }
 98 // 强制退出
 99 var forceoutDialog;
100 function forceoutAction() {
101     //getSelections方法返回所选的行,当没有选择任何行的时候返回一个空数组。
102     var rows = $table.bootstrapTable('getSelections');
103     if (rows.length == 0) {
104         $.confirm({
105             title: false,
106             content: '请至少选择一条记录!',
107             autoClose: 'cancel|3000',
108             backgroundDismiss: true,
109             buttons: {
110                 cancel: {
111                     text: '取消',
112                     btnClass: 'waves-effect waves-button'
113                 }
114             }
115         });
116     } else {
117         forceoutDialog = $.confirm({
118             type: 'red',
119             animationSpeed: 300,
120             title: false,
121             content: '确认强制退出该会话吗?',
122             buttons: {
123                 confirm: {
124                     text: '确认',
125                     btnClass: 'waves-effect waves-button',
126                     action: function () {
127                         var ids = new Array();
128                         for (var i in rows) {
129                             ids.push(rows[i].id);
130                         }
131                         $.ajax({
132                             type: 'get',
133                             url: '${basePath}/manage/session/forceout/' + ids.join(","),
134                             success: function(result) {
135                                 if (result.code != 1) {
136                                     if (result.data instanceof Array) {
137                                         $.each(result.data, function(index, value) {
138                                             $.confirm({
139                                                 theme: 'dark',
140                                                 animation: 'rotateX',
141                                                 closeAnimation: 'rotateX',
142                                                 title: false,
143                                                 content: value.errorMsg,
144                                                 buttons: {
145                                                     confirm: {
146                                                         text: '确认',
147                                                         btnClass: 'waves-effect waves-button waves-light'
148                                                     }
149                                                 }
150                                             });
151                                         });
152                                     } else {
153                                         $.confirm({
154                                             theme: 'dark',
155                                             animation: 'rotateX',
156                                             closeAnimation: 'rotateX',
157                                             title: false,
158                                             content: result.data.errorMsg,
159                                             buttons: {
160                                                 confirm: {
161                                                     text: '确认',
162                                                     btnClass: 'waves-effect waves-button waves-light'
163                                                 }
164                                             }
165                                         });
166                                     }
167                                 } else {
168                                     forceoutDialog.close();
169                                     $table.bootstrapTable('refresh');
170                                 }
171                             },
172                             error: function(XMLHttpRequest, textStatus, errorThrown) {
173                                 $.confirm({
174                                     theme: 'dark',
175                                     animation: 'rotateX',
176                                     closeAnimation: 'rotateX',
177                                     title: false,
178                                     content: textStatus,
179                                     buttons: {
180                                         confirm: {
181                                             text: '确认',
182                                             btnClass: 'waves-effect waves-button waves-light'
183                                         }
184                                     }
185                                 });
186                             }
187                         });
188                     }
189                 },
190                 cancel: {
191                     text: '取消',
192                     btnClass: 'waves-effect waves-button'
193                 }
194             }
195         });
196     }
197 }
198 </script>
199 </body>
200 </html>

common.js

 1 $(function() {
 2     // Waves初始化
 3     Waves.displayEffect();
 4     // 数据表格动态高度
 5     $(window).resize(function () {
 6         $('#table').bootstrapTable('resetView', {
 7             height: getHeight()
 8         });
 9     });
10     // 设置input特效
11     $(document).on('focus', 'input[type="text"]', function() {
12         $(this).parent().find('label').addClass('active');
13     }).on('blur', 'input[type="text"]', function() {
14         if ($(this).val() == '') {
15             $(this).parent().find('label').removeClass('active');
16         }
17     });
18     // select2初始化
19     $('select').select2();
20 });
21 // 动态高度
22 function getHeight() {
23     return $(window).height() - 20;
24 }
25 // 数据表格展开内容
26 function detailFormatter(index, row) {
27     var html = [];
28     $.each(row, function (key, value) {
29         html.push('<p><b>' + key + ':</b> ' + value + '</p>');
30     });
31     return html.join('');
32 }
33 // 初始化input特效
34 function initMaterialInput() {
35     $('form input[type="text"]').each(function () {
36         if ($(this).val() != '') {
37             $(this).parent().find('label').addClass('active');
38         }
39     });
40 }

 

转载于:https://www.cnblogs.com/dream-to-pku/p/9443901.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值