• 关于ssm整合shiro框架


    菜鸟第一次写博客。不足之处多谅解

    shiro需要的jar

            <!--导入shiro-web的依赖 -->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-web</artifactId>
                <version>1.5.3</version>
            </dependency>
            <!-- 导入shiro-core的依赖 -->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-core</artifactId>
                <version>1.5.3</version>
            </dependency>
            <!-- 导入shiro-spring 的依赖-->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>1.5.3</version>
            </dependency>

    1,添加shiro配置文件:applicationContext-shiro.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" xmlns:p="http://www.springframework.org/schema/p"
     4     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
     5     xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
     6     xsi:schemaLocation="
     7         http://www.springframework.org/schema/beans 
     8         http://www.springframework.org/schema/beans/spring-beans.xsd
     9         http://www.springframework.org/schema/util
    10         http://www.springframework.org/schema/util/spring-util.xsd
    11         http://www.springframework.org/schema/aop 
    12         http://www.springframework.org/schema/aop/spring-aop.xsd
    13         http://www.springframework.org/schema/context
    14         http://www.springframework.org/schema/context/spring-context.xsd
    15         http://www.springframework.org/schema/tx
    16         http://www.springframework.org/schema/tx/spring-tx.xsd
    17         http://www.springframework.org/schema/p
    18         http://www.springframework.org/schema/p/spring-p.xsd
    19         ">
    20         
    21     <context:component-scan base-package="cn.ljs.realm"/>
    22     <!-- 
    23     1. 配置securityManager,也就是shiro的核心。
    24      -->
    25     <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    26         <property name="realm" ref="myRealm" />
    27         <!-- 缓存管理器 -->
    28         <property name="cacheManager" ref="cacheManager" />
    29         <property name="sessionManager" ref="sessionManager"></property>
    30 
    31     </bean>
    32     <!-- 
    33     2. 配置cacheManager(缓存管理)
    34      -->
    35     <bean id="cacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager">
    36     </bean>
    37     <!-- 
    38     3. 配置Realm,自己定义的shiroRealm,必须实现org.apache.shiro.realm.Realm这个接口
    39      -->
    40     <bean id="myRealm" class="cn.ljs.realm.MyRealm"></bean>
    41     <!-- 
    42     4.配置lifecycleBeanPostProcessor, 可以自动的来调用配置在spring IOC 容器中shiro bean的生命周期方法 -->
    43     <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
    44     <!-- 
    45     5.启用IOC容器中使用shiro的注解,但必须在配置 lifecycleBeanPostProcessor才可以使用-->
    46     <bean
    47         class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
    48         depends-on="lifecycleBeanPostProcessor" />
    49     <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
    50         <property name="securityManager" ref="securityManager"/>
    51     </bean>
    52     
    53     <!-- 存储登录用户的信息 -->
    54     <bean id="sessionDao" class="org.apache.shiro.session.mgt.eis.MemorySessionDAO"/>
    55     <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
    56         <!-- 设置超时时间 -->
    57         <property name="globalSessionTimeout" value="14400000"/>
    58         <property name="sessionDAO" ref="sessionDao"/>
    59     </bean>
    60     <!-- 
    61     6. 配置shiroFilter
    62     6.1 id必须和web.xml 文件中配置的DelegatingFilterProxy的filter-name一致
    63      -->
    64     <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    65         <property name="securityManager" ref="securityManager" />
    66         <property name="loginUrl" value="/index.jsp" /><!-- 项目未登录访问,默认进入的页面, -->
    67         <!-- <property name="successUrl" value="/user/list.do" />-->
    68         <!-- <property name="unauthorizedUrl" value="/index.jsp" />  -->
    69 
    70         <!-- shiro的过滤器 - 过滤规则
    71                                     常用的过滤器:
    72             authc:必须认证才能通过
    73             anon:游客可以通过
    74             logout:注销的请求
    75          -->
    76         <property name="filterChainDefinitions">
    77             <value>
    78                <!-- 需要放行在这里配置,未放行的会被拦截,如下, -->
    79                 /css/**=anon
    80                 /images/**=anon
    81                 /js/**=anon
    82                 /**=authc   
    83             </value>
    84         </property>
    85 
    86     </bean>
    87 </beans>

    2,spring-mvc添加shiro配置

    <!--Shiro配置-->
        <aop:config proxy-target-class="true"></aop:config>
        <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
            <property name="securityManager" ref="securityManager" />
        </bean>

    3,web.xml添加shiro过滤器

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
             version="3.1" metadata-complete="true">
    
        <!--Shiro过滤器-->
        <filter>
            <filter-name>shiroFilter</filter-name>
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
            <init-param>
                <param-name>transformWsdlLocations</param-name>
                <param-value>true</param-value>
            </init-param>
            <!-- &lt;!&ndash;在from文件上传springContext接收&ndash;&gt; -->
            <init-param>
                <param-name>targetFilterLifecycle</param-name>
                <param-value>true</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>shiroFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
        <!-- 加载spring容器配置 -->
        <listener>
            <listener-class>
                org.springframework.web.context.ContextLoaderListener
            </listener-class>
        </listener>
        <!-- 设置spring容器加载所有的配置文件路径 -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                classpath:spring*.xml
            <!-- 配置文件名字统一就不用下面这个,这个是shiro的配置文件 --> classpath:applicationContext*.xml </param-value> </context-param> <context-param> <param-name/> <param-value/> </context-param> <!-- 配置springMVC核心控制器 --> <servlet> <servlet-name>springMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置初始配置化文件,前面contextConfigLocation看情况二选一 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:spring-mvc.xml </param-value> </init-param> <!-- 启动加载一次 --> <load-on-startup>1</load-on-startup> </servlet> <!--为DispatcherServlet建立映射 --> <servlet-mapping> <servlet-name>springMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 解决工程编码过滤器 --> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <filter-name>CORS</filter-name> <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class> <init-param> <param-name>cors.allowGenericHttpRequests</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>cors.allowOrigin</param-name> <param-value>*</param-value> </init-param> <init-param> <param-name>cors.allowSubdomains</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>cors.supportedMethods</param-name> <param-value>GET, HEAD, POST, OPTIONS</param-value> </init-param> <init-param> <param-name>cors.supportedHeaders</param-name> <param-value>*</param-value> </init-param> <init-param> <param-name>cors.exposedHeaders</param-name> <param-value>X-Test-1, X-Test-2</param-value> </init-param> <init-param> <param-name>cors.supportsCredentials</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>cors.maxAge</param-name> <param-value>3600</param-value> </init-param> </filter> <filter-mapping> <filter-name>CORS</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>

    4,自定义一个 myRealm,名字要跟配置一样

     里面核心代码:用户认证核心逻辑看需要什么,这里只写大致逻辑

    package cn.ljs.realm;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.AuthenticationInfo;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.SimpleAuthenticationInfo;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.mgt.eis.SessionDAO;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.subject.support.DefaultSubjectContext;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.stereotype.Service;
    
    import cn.ljs.entity.SysResc;
    import cn.ljs.entity.SysRole;
    import cn.ljs.entity.SysUser;
    import cn.ljs.service.SysUserLoginService;
    
    import java.net.SocketException;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import javax.servlet.http.HttpServletRequest;
    
    
    /**
     * Shiro的数据源
     */
    
    @Component
    public class MyRealm extends AuthorizingRealm {/**
         * 权限控制 - 每次验证权限时都会调用
         * @param principals
         * @return
         */
    
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            SysUser user = (SysUser) principals.getPrimaryPrincipal();
    
            //从用户对象中直接获得权限列表
            //List<SysResc> rescs = user.getSysResc();

          String string = user.getSysRole().getRescs();
          SysResc sysResc = new SysResc();
          sysResc.setRquanxian(string);
          List<SysResc> rescs = new ArrayList<>();
          rescs.add(sysResc);


        
    if(rescs != null || role!=null){ SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); for (SysResc resc : rescs) { if(resc.getRquanxian() != null && !"".equals(resc.getRquanxian())) { simpleAuthorizationInfo.addStringPermission(resc.getRquanxian()); } }
            //simpleAuthorizationInfo.addRole(rolename);//也可以根据需要存入角色名字,名字从user对象获取
    return simpleAuthorizationInfo; } return null; } /** * 身份认证 * @param token * @return * @throws AuthenticationException */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    
            //获得登录时的用户名
            String username = (String) token.getPrincipal();
         SysUser user=new SysUser();

              //通过用户名查询用户信息
              List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();
              Map<String, Object> map=new HashMap<String, Object>();
              list = userLogin.queryUser(username);

    
    

              for(int i=0;i<list.size();i++) {//数据就用了三张表,用户表,角色表,权限表,没有用中间表,权限表是一个字典表,
                  map=list.get(i);
                  //查出来的账号信息全部放入实体类就行,比如。

                   user.setName((String)map.get("name"));//名字

             //角色信息

             SysRole role=new SysRole();

             //登录时一并查出来的角色信息放进去,就列举一个,需要什么放什么,下面的权限我这里是用数字代替,比如:1,2,3。最后有一个图片,是我这里使用的权限字典表

                  role.setRescs((String) map2.get("rescs"));//权限,这里存入的信息在后面会用到。比如上面的权限控制:doGetAuthorizationInfo

                  user.setSysRole(role);

    }

            if(user != null){//将用户认证信息存入shiro框架
                SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(), this.getName());
                return simpleAuthenticationInfo;
            }else {
    
            }
            return null;
        }
    }

    5,登录方法调用,以及保证线上同一个账号只允许一个在线,其他的通通挤下线,

      有两个登录方法:

          1,第一个是做了登录次数限制,密码错误三次十分钟之内不可以再次尝试登录,如果密码输入错误总次数大于十次,账号会被锁定。需要在用户表增加三个字段,再根据项目做调整。

    package cn.ljs.controller;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.IncorrectCredentialsException;
    import org.apache.shiro.authc.UnknownAccountException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.mgt.DefaultSecurityManager;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.mgt.DefaultSessionManager;
    import org.apache.shiro.subject.Subject;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import cn.ljs.entity.ClientIP;
    import cn.ljs.entity.Logtable;
    import cn.ljs.entity.SysUser;
    import cn.ljs.service.LogtableService;
    import cn.ljs.service.SysUserLoginService;
    import cn.ljs.util.Loggings;
    import cn.ljs.util.MD5;
    import cn.ljs.util.TimeUtil;
    
    @Controller
    @RequestMapping("/loginController")
    public class LoginController {
        
        @Autowired
        private SysUserLoginService userLogin;
        //private UserManageService userservice;
        
        @Autowired
        private LogtableService logtableService;
        
         @RequestMapping("/login")
         @ResponseBody
        public List<String> login(String username, String password, Model model,HttpServletRequest request,
                HttpServletResponse response){
             List<String> list = new ArrayList<>();
             String ret="";
             String ip = request.getHeader("x-forwarded-for");  
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
            //交给shiro进行认证
            Subject subject = SecurityUtils.getSubject();
            //对密码加密处理
            password = MD5.makeMD5(password);  
            //获得系统时间,与账号最后登录时间对比,密码错误超过3次禁用10分钟,超过10次锁定账号
            Date date = new Date();
            SimpleDateFormat sdf =   new SimpleDateFormat( " yyyy-MM-dd HH:mm:ss " );
            String nowTime = sdf.format(date);
            Date time = null;
            try {
                time = sdf.parse( nowTime );
            } catch (ParseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            //获取账号状态,判断是否已被锁定,statesum大于10则锁定,
            SysUser users=new SysUser();
            List<Map<String, Object>> userlist = new ArrayList<Map<String,Object>>();
            Map<String, Object> map=new HashMap<String, Object>();
            userlist = userLogin.queryUser(username);
            for(int i=0;i<userlist.size();i++) {
                map=userlist.get(i);
                users.setId((Integer) map.get("id"));
                users.setState((Integer) map.get("state"));
                users.setStatesum((Integer) map.get("statesum"));
                users.setLogintime((Date) map.get("logintime"));
            }
            Integer state2 = users.getState();
            Integer statesum2 = users.getStatesum();
            if(statesum2==null) {
                statesum2=0;
            }
            //state=3,logintime<10分钟为临时锁定,十分钟后才可以登录
            if(users.getLogintime()!=null && state2!=null) {
                //计算时间差(分钟)
                long datePoor = TimeUtil.getDatePoor(users.getLogintime());
                //时间超过十分钟后更新当前账号状态
                if (statesum2>9) {
                    ret = "账号已被锁定,请联系管理员!";
                    list.add(ret); 
                    return list;
                }else if(state2>2 && datePoor<10) {
                    ret = "账号已被锁定十分钟,请稍后重试!";
                    list.add(ret); 
                    return list;
                }else if(datePoor>10){
                    users.setState(null);
                    //锁定十分钟后,清空state次数
                    userLogin.updateState(users);
                }
            }
    
            
            if(!subject.isAuthenticated()){
    
                UsernamePasswordToken token = new UsernamePasswordToken(username, password);
                try {
                    subject.login(token);
                 // 剔除其他此账号在其它地方登录
                    List<Session> loginedList = getLoginedSession(subject);
                    for (Session session : loginedList) {
                        session.stop();
                    } 
                } catch (UnknownAccountException ex1) {
                    ex1.printStackTrace();
                    ret = "账号或密码错误,请重新输入!";
                    list.add(ret);  
                    return list;
                } catch (IncorrectCredentialsException ex2) { 
                    ex2.printStackTrace();
                    
                    //重新查询账号状态
                    SysUser u = new SysUser();
                    List<Map<String, Object>> userlists = new ArrayList<Map<String,Object>>();
                    Map<String, Object> maps=new HashMap<String, Object>();
                    userlists = userLogin.queryUser(username);
                    for(int i=0;i<userlists.size();i++) {
                        maps=userlists.get(i);
                        u.setId((Integer) maps.get("id"));
                        u.setState((Integer) maps.get("state"));
                        u.setStatesum((Integer) maps.get("statesum"));
                        u.setLogintime((Date) maps.get("logintime"));
                        u.setLasttime((Date) maps.get("lasttime"));
                    }
                    
                    Integer state = u.getState();//错误次数
                    Integer statesum = u.getStatesum();
                    
                    if(state==null && statesum==null) {
                        state=1;
                        u.setState(state);
                        u.setStatesum(state);
                        u.setLogintime(time);//登录失败,密码错误,当前登录时间
                        userLogin.updateState(u);
                        ret = "账号或密码错误,您还有"+(3-state)+"次输入机会!";
                        list.add(ret); 
                        return list;
                    }else if(statesum>8) {
                        statesum=statesum+1;
                        state=3;
                        u.setStatesum(statesum);//
                        u.setState(state);
                        u.setLogintime(time);//登录失败,密码错误,当前登录时间
                        userLogin.updateState(u);
                        ret = "账号已被锁定,请联系管理员!";
                        list.add(ret); 
                        return list;
                    }else if (state == null) {
                        state=1;
                        statesum=statesum+1;
                        u.setState(state);
                        u.setStatesum(statesum);
                        u.setLogintime(time);//登录失败,密码错误,当前登录时间
                        userLogin.updateState(u);
                        ret = "账号或密码错误,您还有"+(3-state)+"次输入机会!";
                        list.add(ret); 
                        return list;
                    }else if (statesum == null) {
                        statesum=1;
                        u.setState(state);
                        u.setStatesum(state);
                        u.setLogintime(time);//登录失败,密码错误,当前登录时间
                        userLogin.updateState(u);
                        ret = "账号或密码错误,您还有"+(3-state)+"次输入机会!";
                        list.add(ret); 
                        return list;
                    }else if(state<2) {
                        state=state+1;
                        statesum=statesum+1;
                        u.setState(state);//
                        u.setStatesum(statesum);//更新失败总次数
                        u.setLogintime(time);//登录失败,密码错误,当前登录时间
                        userLogin.updateState(u);
                        ret = "账号或密码错误,您还有"+(3-state)+"次输入机会!";
                        list.add(ret); 
                        return list;
                    }else{
                        state=state+1;
                        statesum=statesum+1;
                        u.setState(state);
                        u.setStatesum(statesum);//
                        u.setLogintime(time);//登录失败,密码错误,当前登录时间
                        userLogin.updateState(u);
                        ret = "账号已被锁定十分钟,请稍后重试!";
                        list.add(ret); 
                        return list;
                    }
                }catch (AuthenticationException ex3) {  
                    ret = "账号或密码错误,请重新输入!";
                    list.add(ret); 
                    return list;
                }
            }
    
            Integer state = users.getState();
            Integer statesum = users.getStatesum();
            if(state!=null) {
                if(state>2) {
                    ret = "账号已被锁定十分钟,请稍后重试!";
                    list.add(ret); 
                    return list;
                }else if ( statesum>9) {
                    ret = "账号已被锁定,请联系管理员!";
                    list.add(ret); 
                    return list;
                }else {
                    ret="登录成功";
                    list.add(ret);
                }
            }else {
                ret="登录成功";
                list.add(ret);
            }
            //获得当前认证的对象
            SysUser user = (SysUser) subject.getPrincipal();
            user.setState(null);
            user.setStatesum(null);
            user.setLogintime(null);
            user.setLasttime(time);
            user.setLastip(ip);
            userLogin.updateState(user);
            
            //将权限存入session,页面通过Ajax调用存入session的权限
            HttpSession session = request.getSession();
            String rolename = user.getSysRole().getRolename();
            if(!session.equals("")||session!=null) {
                session.setAttribute("user", user.getSysResc());
                session.setAttribute("id", user.getId());
                session.setAttribute("role", user.getRoles());
                session.setAttribute("account", user.getAccount());
                session.setAttribute("password", user.getPassword());
                session.setAttribute("name", user.getName());
                session.setAttribute("rolename", rolename);
            }
    return list;
        }
         
    
        //遍历同一个账户的session
        private List<Session> getLoginedSession(Subject currentUser) {
            Collection<Session> list = ((DefaultSessionManager) ((DefaultSecurityManager) SecurityUtils
                    .getSecurityManager()).getSessionManager()).getSessionDAO()
                    .getActiveSessions();
            List<Session> loginedList = new ArrayList<Session>();
            SysUser loginUser = (SysUser) currentUser.getPrincipal();
            for (Session session : list) {
                Subject s = new Subject.Builder().session(session).buildSubject();
                if (s.isAuthenticated()) {
                    SysUser user = (SysUser) s.getPrincipal();
                    if (user.getId()==(loginUser.getId())) {
                        if (!session.getId().equals(currentUser.getSession().getId())) {
                            loginedList.add(session);
                        }
                    }
                }
            }
            return loginedList;
        }
    
    }

    2,第二个没有限制,只要认证成功就可以。

    package cn.ljs.controller;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.IncorrectCredentialsException;
    import org.apache.shiro.authc.UnknownAccountException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.mgt.DefaultSecurityManager;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.mgt.DefaultSessionManager;
    import org.apache.shiro.subject.Subject;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import cn.ljs.entity.ClientIP;
    import cn.ljs.entity.Logtable;
    import cn.ljs.entity.SysUser;
    import cn.ljs.service.LogtableService;
    import cn.ljs.service.SysUserLoginService;
    import cn.ljs.util.Loggings;
    import cn.ljs.util.MD5;
    import cn.ljs.util.TimeUtil;
    
    @Controller
    @RequestMapping("/loginController")
    public class LoginController {
        
        @Autowired
        private SysUserLoginService userLogin;
        //private UserManageService userservice;
        
        @Autowired
        private LogtableService logtableService;
        
         @RequestMapping("/login")
         @ResponseBody
        public List<String> login(String username, String password, Model model,HttpServletRequest request,
                HttpServletResponse response){
             List<String> list = new ArrayList<>();
             String ret="";//登录返回值随自己定义,
            //交给shiro进行认证
            Subject subject = SecurityUtils.getSubject();if(!subject.isAuthenticated()){
                UsernamePasswordToken token = new UsernamePasswordToken(username, password);
                try {
                    subject.login(token);
                 // 剔除其他此账号在其它地方登录
                    List<Session> loginedList = getLoginedSession(subject);
                    for (Session session : loginedList) {
                        session.stop();
                    } 
                } catch (UnknownAccountException ex1) {
                    ex1.printStackTrace();
              ret = "账号错误";
    } catch (IncorrectCredentialsException ex2) { ex2.printStackTrace();
              ret = "密码错误"; 
    }catch (AuthenticationException ex3) { //ex3.printStackTrace();
              //ret = "该账号不存在";
    ret = "账号或密码错误,请重新输入!"; list.add(ret); return list; } } return list; } //遍历同一个账户的session private List<Session> getLoginedSession(Subject currentUser) { Collection<Session> list = ((DefaultSessionManager) ((DefaultSecurityManager) SecurityUtils .getSecurityManager()).getSessionManager()).getSessionDAO() .getActiveSessions(); List<Session> loginedList = new ArrayList<Session>(); SysUser loginUser = (SysUser) currentUser.getPrincipal(); for (Session session : list) { Subject s = new Subject.Builder().session(session).buildSubject(); if (s.isAuthenticated()) { SysUser user = (SysUser) s.getPrincipal(); if (user.getId()==(loginUser.getId())) { if (!session.getId().equals(currentUser.getSession().getId())) { loginedList.add(session); } } } } return loginedList; } }

    6,计算时间工具类,获取系统当前时间和账号登录失败时间,大于等于10分钟允许重新登录,

    package cn.ljs.util;
    
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class TimeUtil {
        
    /*    public static long getDatePoor(Date endDate, Date nowDate) {
             
            long nd = 1000 * 24 * 60 * 60;
            long nh = 1000 * 60 * 60;
            long nm = 1000 * 60;
            // long ns = 1000;
            // 获得两个时间的毫秒时间差异
            long diff = endDate.getTime() - nowDate.getTime();
            // 计算差多少天
            //long day = diff / nd;
            // 计算差多少小时
            //long hour = diff % nd / nh;
            // 计算差多少分钟
            long min = diff % nd % nh / nm;
            // 计算差多少秒//输出结果
            // long sec = diff % nd % nh % nm / ns;
            return  min;
        }*/
    
    
        public static long getDatePoor(Date endDate) {
            String data = endDate.toString();
            long dateMethod = dateMethod(data);
            System.out.println("分钟数:" + dateMethod);
    //        currTime();
            return dateMethod;
        }
     
        /**
         * 计算时间差(单位:分钟)
         * @param lastReceiveTime    
         * @return
         */
        private static long dateMethod(String lastReceiveTime) {
            System.out.println("最后时间" + lastReceiveTime);
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                Date date1 = df.parse(currTime());
                Date date2 = df.parse(lastReceiveTime);
                long diff = date1.getTime() - date2.getTime();
                System.out.println("毫秒数:" + diff);
                //计算两个时间之间差了多少分钟
                long minutes = diff / (1000 * 60);
                return minutes;
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return 0;
        }
        
        /**
         * 得到当前时间    yyyy-MM-dd HH:mm:ss格式
         * @return    当前时间
         */
        private static String currTime() throws Exception{
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date = new Date();
            String currTime = df.format(date);
            System.out.println("当前时间" + currTime);
            return currTime;
        }
    }

    7,jsp使用shiro标签,页面需要引入shiro标签库,

      

    <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
    
    //测试是否成功,name是后台查询出来存入shiro的user对象里的值,页面需要什么,后台就存什么。其他标签可自行百度
    <shiro:user>
          <shiro:principal property="name"</shiro:principal>
    </shiro:user>

    列举如下几个页面常用标签:更多标签请百度。。。
    <shiro:hasAnyRoles name="管理员,普通角色">
      123
    </shiro:hasAnyRoles>//如果拥有管理员或者普通角色的其中一个,123就会显示。没有就不显示

    <shiro:hasPermission name="1">//如果拥有权限1,456就会显示,没有就不显示
      456
    </shiro:hasPermission>

    <shiro:lacksPermission name="1">//除了有1权限的不会显示789,其他都能显示
      789
    </shiro:lacksPermission>

    controller注解式:
      @RequiresRoles("超级管理员")//拥有该角色可以访问

      更多注解式使用方法:https://blog.csdn.net/qi923701/article/details/75224554

     贴上我的权限字典表,上面标签里的name值对应下图中的rquanxian值。正常的话是五张表,用户表,角色表,权限表,用户和角色中间表,角色和权限中间表,这里看项目需求,怎么简单方便怎么来。

  • 相关阅读:
    初识ES6
    初识NODE
    AJAX详解
    PHP 文件与目录操作函数总结
    PHP封装一个通用好用的文件上传处理类
    PHP基础之 错误处理 及 异常处理
    PHP基础OOP(二) 多态
    PHP基础之 重载 的实现方式
    CCS3的过渡、变换、动画以及响应式布局、弹性布局
    CSS之盒子模型(由浅到深的理解)
  • 原文地址:https://www.cnblogs.com/ljmm/p/12582714.html
Copyright © 2020-2023  润新知