zoukankan      html  css  js  c++  java
  • 关于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值。正常的话是五张表,用户表,角色表,权限表,用户和角色中间表,角色和权限中间表,这里看项目需求,怎么简单方便怎么来。

  • 相关阅读:
    Account group in ERP and its mapping relationship with CRM partner group
    错误消息Number not in interval XXX when downloading
    错误消息Form of address 0001 not designated for organization
    Algorithm类介绍(core)
    梯度下降与随机梯度下降
    反思
    绘图: matplotlib核心剖析
    ORB
    SIFT
    Harris角点
  • 原文地址:https://www.cnblogs.com/ljmm/p/12582714.html
Copyright © 2011-2022 走看看