zoukankan      html  css  js  c++  java
  • 【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 # u7EC8u7AEFu7C7Bu578B
    21 zheng.upms.type=server
    22 # u7EC8u7AEFsessionu540Du79F0
    23 zheng.upms.session.id=zheng-upms-server-session-id
    24 # u4F1Au8BDDu65F6u957F,u534Au5C0Fu65F6uFF08u5355u4F4Du6BEBu79D2uFF09
    25 zheng.upms.session.timeout=1800000
    26 # u5355u70B9u767Bu5F55u8BA4u8BC1u4E2Du5FC3u5730u5740
    27 #zheng.upms.sso.server.url=http://upms.zhangshuzheng.cn:1111
    28 zheng.upms.sso.server.url=http://127.0.0.1:1111
    29 # u767Bu5F55u6210u529Fu56DEu8C03u5730u5740
    30 zheng.upms.successUrl=/manage/index
    31 # u672Au6388u6743u5730u5740
    32 zheng.upms.unauthorizedUrl=/403
    33 # u8BB0u4F4Fu5BC6u7801u65F6u957F30u5929
    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:;" onclick="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 }
  • 相关阅读:
    tp5最强分页 自定义model,控制器引用。只显示一页
    tp5分页,一看就懂,简单明了(附带额外参数)
    PHP 验证5-20位数字加字母的正则(数字和字母缺一不可)!!!
    表格样式
    tp5中很牛皮的一句sql语句,三个条件(两个不确定条件,一个硬性条件)
    centos6.8下搭建git和gitlab版本库
    解决 nginx: [alert] kill(1022, 1) failed (3: No such process)
    Zabbix利用msmtp+mutt发送邮件报警
    nginx基本配置与参数说明
    Linux添加/删除用户和用户组
  • 原文地址:https://www.cnblogs.com/dream-to-pku/p/9443901.html
Copyright © 2011-2022 走看看