zoukankan      html  css  js  c++  java
  • springboot shiro 重复登录 剔除

    springboot整合shiro后。

    当同一个用户重复登录时,默认会两个都登录成功,两个session。

    目标是:当第二次登录时,把第一个session剔除。不允许重复登录

    小知识:同一个浏览器,用两个标签页分别登录,是同一个session。

    两个浏览器登录,是两个session。

    ShiroConfiguration.java

    package com.zfzn.hospital_backend.application;


    import com.zfzn.hospital_backend.shiro.AuthRealm;
    import com.zfzn.hospital_backend.shiro.CredentialsMatcher;
    import org.apache.shiro.cache.ehcache.EhCacheManager;
    import org.apache.shiro.spring.LifecycleBeanPostProcessor;
    import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.mgt.CookieRememberMeManager;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.apache.shiro.web.servlet.SimpleCookie;
    import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.DependsOn;

    import java.util.LinkedHashMap;

    /**
    * shiro的配置类
    * @author Administrator
    *
    */
    @Configuration
    public class ShiroConfiguration {
    private static final Logger logger = LoggerFactory.getLogger(ShiroConfiguration.class);
    /**
    * ShiroFilterFactoryBean,是个factorybean,为了生成ShiroFilter。
    * 它主要保持了三项数据,securityManager,filters,filterChainDefinitionManager。
    *
    * @return
    */
    @Bean(name="shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") org.apache.shiro.mgt.SecurityManager manager) {
    logger.info("ShiroConfiguration.shiroFilter()");
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    // 必须设置SecuritManager
    shiroFilterFactoryBean.setSecurityManager(manager);

    // Map<String, Filter> filtersMap = shiroFilterFactoryBean.getFilters();
    // filtersMap.put("authc", myFormAuthenticationFilter(manager));// 自定义拦截器
    // shiroFilterFactoryBean.setFilters(filtersMap);

    // 拦截器
    //配置登录的url和登录成功的url
    shiroFilterFactoryBean.setLoginUrl("/user/login");
    // bean.setSuccessUrl("/home");
    //配置访问权限
    LinkedHashMap<String, String> filterChainDefinitionMap=new LinkedHashMap<>();
    // filterChainDefinitionMap.put("/jsp/login.jsp*", "anon"); //表示可以匿名访问
    // filterChainDefinitionMap.put("/loginUser", "anon");
    // filterChainDefinitionMap.put("/logout*","anon");
    // filterChainDefinitionMap.put("/jsp/error.jsp*","anon");
    // filterChainDefinitionMap.put("/jsp/index.jsp*","authc");
    // filterChainDefinitionMap.put("/*", "authc");//表示需要认证才可以访问
    // filterChainDefinitionMap.put("/**", "authc");//表示需要认证才可以访问
    // filterChainDefinitionMap.put("/*.*", "authc");

    filterChainDefinitionMap.put("/upload/**","authc");
    filterChainDefinitionMap.put("/KeyDevice/**", "authc");//表示需要认证才可以访问
    filterChainDefinitionMap.put("/CoolingTower/**", "authc");
    filterChainDefinitionMap.put("/CoolingTowerDetail/**", "authc");
    filterChainDefinitionMap.put("/Refrigerating/**", "authc");
    filterChainDefinitionMap.put("/RefrigeratingDetail/**", "authc");
    filterChainDefinitionMap.put("/LKInterface/**", "authc");
    filterChainDefinitionMap.put("/hospitalService/**", "authc");
    filterChainDefinitionMap.put("/historyData/**", "authc");
    filterChainDefinitionMap.put("/deviceManage/**", "authc");
    filterChainDefinitionMap.put("/dictionary/**", "authc");
    filterChainDefinitionMap.put("/WebSocketService/**", "authc");
    filterChainDefinitionMap.put("/AccidentRecord/**", "authc");
    filterChainDefinitionMap.put("/DataUpload/**", "authc");
    filterChainDefinitionMap.put("/DataUploadLog/**", "authc");
    filterChainDefinitionMap.put("/NewTrendDetail/getNewTrendDetail/**", "authc");
    filterChainDefinitionMap.put("/NewTrend/**", "authc");
    filterChainDefinitionMap.put("/ServiceProvider/**", "authc");
    filterChainDefinitionMap.put("/buildService/**", "authc");
    filterChainDefinitionMap.put("/Sewage/**", "authc");
    filterChainDefinitionMap.put("/SewageDetail/**", "authc");
    filterChainDefinitionMap.put("/AirCondtion/**", "authc");
    filterChainDefinitionMap.put("/AirCondtionDetail/**", "authc");
    filterChainDefinitionMap.put("/AccidentRecord/**", "authc");
    filterChainDefinitionMap.put("/system/**", "authc");
    filterChainDefinitionMap.put("/Repairman/**", "authc");
    filterChainDefinitionMap.put("/maintainInspection/**", "authc");
    filterChainDefinitionMap.put("/RepairmanTeam/**", "authc");
    filterChainDefinitionMap.put("/EnergyConsumption/**", "authc");
    filterChainDefinitionMap.put("/DeviceGroup/**", "authc");
    filterChainDefinitionMap.put("/device/**", "authc");
    filterChainDefinitionMap.put("/AnlysisRepair/**", "authc");
    filterChainDefinitionMap.put("/AnlysisMaintain/**", "authc");
    filterChainDefinitionMap.put("/propertyManage/**", "authc");
    filterChainDefinitionMap.put("/Boiler/**", "authc");
    filterChainDefinitionMap.put("/BoilerDetail/**", "authc");
    filterChainDefinitionMap.put("/QueryConfigure/**", "authc");
    filterChainDefinitionMap.put("/elevator/**", "authc");


    // // 如果不设置默认会自动寻找工程根目录下的"/login"页面
    // shiroFilterFactoryBean.setLoginUrl("/login");
    // // 登录成功后要跳转的链接
    // shiroFilterFactoryBean.setSuccessUrl("/index");
    // // 未授权界面;
    // shiroFilterFactoryBean.setUnauthorizedUrl("/403");
    // 加载shiroFilter权限控制规则
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    return shiroFilterFactoryBean;

    }

    //配置核心安全事务管理器
    @Bean(name="securityManager")
    public org.apache.shiro.mgt.SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm) {
    System.err.println("--------------shiro已经加载----------------");
    DefaultWebSecurityManager manager=new DefaultWebSecurityManager();
    manager.setRealm(authRealm);
    manager.setSessionManager(sessionManager());
    // <!-- 用户授权/认证信息Cache, 采用EhCache 缓存 -->
    manager.setCacheManager(ehCacheManager());
    //注入记住我管理器;
    manager.setRememberMeManager(rememberMeManager());
    return manager;
    }

    @Bean(name = "sessionManager")
    public DefaultWebSessionManager sessionManager() {
    DefaultWebSessionManager sessionManager=new DefaultWebSessionManager();
    return sessionManager;
    }
    //配置自定义的权限登录器
    @Bean(name="authRealm")
    public AuthRealm authRealm(@Qualifier("credentialsMatcher") CredentialsMatcher matcher) {
    System.out.println("authRealm");
    AuthRealm authRealm=new AuthRealm();
    authRealm.setCredentialsMatcher(matcher);
    return authRealm;
    }
    //配置自定义的密码比较器
    @Bean(name="credentialsMatcher")
    public CredentialsMatcher credentialsMatcher() {
    System.out.println("credentialsMatcher");
    return new CredentialsMatcher();
    }
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") org.apache.shiro.mgt.SecurityManager manager) {
    System.out.println("authorizationAttributeSourceAdvisor");
    AuthorizationAttributeSourceAdvisor advisor=new AuthorizationAttributeSourceAdvisor();
    advisor.setSecurityManager(manager);
    return advisor;
    }

    //-----------------------------------------------
    /**
    * LifecycleBeanPostProcessor,这是个DestructionAwareBeanPostProcessor的子类,
    * 负责org.apache.shiro.util.Initializable类型bean的生命周期的,初始化和销毁。
    * 主要是AuthorizingRealm类的子类,以及EhCacheManager类。
    *
    * @return
    */
    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
    logger.info("ShiroConfiguration.getLifecycleBeanPostProcessor()");
    return new LifecycleBeanPostProcessor();
    }

    /**
    * HashedCredentialsMatcher,这个类是为了对密码进行编码的,防止密码在数据库里明码保存,
    * 当然在登陆认证的生活,这个类也负责对form里输入的密码进行编码。
    *
    * @return
    */
    // @Bean(name = "hashedCredentialsMatcher")
    // public HashedCredentialsMatcher hashedCredentialsMatcher() {
    // HashedCredentialsMatcher credentialsMatcher = new
    // HashedCredentialsMatcher();
    // credentialsMatcher.setHashAlgorithmName("MD5");
    // credentialsMatcher.setHashIterations(2);
    // credentialsMatcher.setStoredCredentialsHexEncoded(true);
    // return credentialsMatcher;
    // }
    /**
    * ShiroRealm,这是个自定义的认证类,继承自AuthorizingRealm, 负责用户的认证和权限的处理
    *
    * @return
    */
    @Bean(name = "myShiroRealm")
    @DependsOn("lifecycleBeanPostProcessor")
    public AuthRealm myShiroRealm() {
    logger.info("ShiroConfiguration.myShiroRealm()");
    AuthRealm myShiroRealm = new AuthRealm();
    return myShiroRealm;
    }

    /**
    * EhCacheManager,缓存管理,用户登陆成功后,把用户信息和权限信息缓存起来,
    * 然后每次用户请求时,放入用户的session中,如果不设置这个bean,每个请求都会查询一次数据库。
    *
    * @return
    */
    @Bean(name = "ehCacheManager")
    @DependsOn("lifecycleBeanPostProcessor")
    public EhCacheManager ehCacheManager() {
    logger.info("ShiroConfiguration.ehCacheManager()");
    EhCacheManager cacheManager = new EhCacheManager();
    cacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
    return cacheManager;
    }

    @Bean(name = "rememberMeCookie")
    public SimpleCookie rememberMeCookie() {
    logger.info("ShiroConfiguration.rememberMeCookie()");
    // 这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
    SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
    // <!-- 记住我cookie生效时间30天 ,单位秒;-->
    simpleCookie.setMaxAge(259200);
    return simpleCookie;
    }
    /**
    * cookie管理对象;
    *
    * @return
    */
    @Bean(name = "rememberMeManager")
    public CookieRememberMeManager rememberMeManager() {
    logger.info("ShiroConfiguration.rememberMeManager()");
    CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
    cookieRememberMeManager.setCookie(rememberMeCookie());
    return cookieRememberMeManager;
    }




    // @Bean
    // public MyFormAuthenticationFilter myFormAuthenticationFilter(@Qualifier("securityManager") org.apache.shiro.mgt.SecurityManager manager) {
    // MyFormAuthenticationFilter myFormAuthenticationFilter = new MyFormAuthenticationFilter();
    // myFormAuthenticationFilter.setSecurityManager(manager);
    // return myFormAuthenticationFilter;
    // }

    /**
    * DefaultAdvisorAutoProxyCreator,Spring的一个bean,由Advisor决定对哪些类的方法进行AOP代理。
    *
    * @return
    */
    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    logger.info("ShiroConfiguration.defaultAdvisorAutoProxyCreator()");
    DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
    daap.setProxyTargetClass(true);
    return daap;
    }


    }

    _____________________________________________________________
    AuthRealm.java

    package com.zfzn.hospital_backend.shiro;

    import com.zfzn.hospital_backend.dao.IotdModuleDao;
    import com.zfzn.hospital_backend.dao.IotdModuleRoleDao;
    import com.zfzn.hospital_backend.dao.IotdRoleDao;
    import com.zfzn.hospital_backend.dao.IotdUserDao;
    import com.zfzn.hospital_backend.entity.IotdModuleEntity;
    import com.zfzn.hospital_backend.entity.IotdModuleRoleEntity;
    import com.zfzn.hospital_backend.entity.IotdRoleEntity;
    import com.zfzn.hospital_backend.entity.IotdUserEntity;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.*;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.mgt.SessionsSecurityManager;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.mgt.DefaultSessionManager;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.springframework.beans.factory.annotation.Autowired;

    import java.util.*;

    public class AuthRealm extends AuthorizingRealm {
    @Autowired
    private IotdUserDao iotdUserDao;
    @Autowired
    IotdRoleDao iotdRoleDao;

    @Autowired
    IotdModuleRoleDao iotdModuleRoleDao;

    @Autowired
    IotdModuleDao iotdModuleDao;

    //认证.登录
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    System.out.println("------------------------------------doGetAuthenticationInfo(AuthenticationToken token)");
    UsernamePasswordToken utoken = (UsernamePasswordToken) token;//获取用户输入的token
    String username = utoken.getUsername();
    System.out.println("username=" + username);
    System.out.println("password=" + utoken.getPassword());

    //处理session
    SessionsSecurityManager securityManager = (SessionsSecurityManager) SecurityUtils.getSecurityManager();
    DefaultSessionManager sessionManager = (DefaultSessionManager) securityManager.getSessionManager();
    Collection<Session> sessions = sessionManager.getSessionDAO().getActiveSessions();//获取当前已登录的用户session列表
    for (Session session : sessions) {
    //清除该用户以前登录时保存的session
    // IotdUserEntity en=(IotdUserEntity)(session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY));
    // String phone=en.getPhone();
    //如果和当前session是同一个session,则不剔除
    if (SecurityUtils.getSubject().getSession().getId().equals(session.getId()))
    break;
    IotdUserEntity user = (IotdUserEntity) (session.getAttribute("user"));
    if (user != null) {
    String phone = user.getPhone();
    if (username.equals(phone)) {
    System.out.println(username + "已登录,剔除中...");
    sessionManager.getSessionDAO().delete(session);
    }
    }
    }


    // User user = userService.findUserByUserName(username);
    IotdUserEntity user = iotdUserDao.findDistinctByPhone(username);
    SimpleAuthenticationInfo rst = new SimpleAuthenticationInfo(user, user.getPwd(), this.getClass().getName());//放入shiro.调用CredentialsMatcher检验密码
    return rst;
    }

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
    System.out.println("----------------------doGetAuthorizationInfo(PrincipalCollection principal)");
    IotdUserEntity user = (IotdUserEntity) principal.fromRealm(this.getClass().getName()).iterator().next();//获取session中的用户
    List<String> permissions = new ArrayList<>();
    // Set<Role> roles = user.getRoleid();
    Integer roleid = user.getRoleid();
    System.out.println("roleid=" + roleid);

    String roleName = "";
    if (roleid > 0) {
    IotdRoleEntity role = iotdRoleDao.findDistinctById(roleid);
    roleName = role.getRole();
    List<IotdModuleRoleEntity> moduleRoleList = iotdModuleRoleDao.findByRoleid(roleid);
    for (IotdModuleRoleEntity moduleRole : moduleRoleList) {
    Integer module_id = moduleRole.getModuleId();
    IotdModuleEntity module = iotdModuleDao.findById(module_id);
    permissions.add(module.getMname());
    }
    }
    System.out.println("permissions=" + permissions);
    SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

    Set<String> roles = new HashSet<>();
    roles.add(roleName);
    info.setRoles(roles);

    info.addStringPermissions(permissions);//将权限放入shiro中.
    return info;
    }

    }

    ______________________________________________________________________________
    CredentialsMatcher.java

    package com.zfzn.hospital_backend.shiro;


    import org.apache.shiro.authc.AuthenticationInfo;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;

    public class CredentialsMatcher extends SimpleCredentialsMatcher {

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
    System.out.println("doCredentialsMatch");
    UsernamePasswordToken utoken=(UsernamePasswordToken) token;
    //获得用户输入的密码:(可以采用加盐(salt)的方式去检验)
    String inPassword = new String(utoken.getPassword());
    System.out.println("获得用户输入的密码:"+inPassword);
    //获得数据库中的密码
    String dbPassword=(String) info.getCredentials();
    System.out.println("获得数据库中的密码:"+dbPassword);
    //进行密码的比对
    return this.equals(inPassword, dbPassword);
    }
    }



  • 相关阅读:
    前端面试的一道数组元素值去重问题
    数组元素前移,第一个元素放置数组末位
    Linux 查询oracle错误日志&警告日志
    CentOS 6.4 源码安装MySQL 5.6
    Oracle 表空间不足引起的问题及解决方法
    Oracle 强制中止正在执行的SQL语句
    request for member 'GetByteArrayElements'
    jni入门 eclipsecygwin+ndk
    ffmpeg结构体(二)
    ffmpeg结构体(三)
  • 原文地址:https://www.cnblogs.com/zhanying999666/p/8392592.html
Copyright © 2011-2022 走看看