springboot+shiro+session+redis+ngnix共享

一:集成redis(单机版:后期再改集群)

1.配置application.properties

#cache指定缓存类型
spring.cache.type=REDIS

#data-redis
spring.redis.database=15
spring.redis.host=192.168.**.** spring.redis.password= spring.redis.port=6379 spring.redis.timeout=2000 spring.redis.jedis.pool.max-active=8 spring.redis.jedis.pool.max-idle=8 spring.redis.jedis.pool.max-wait=-1 spring.redis.jedis.pool.min-idle=0 #spring.redis.sentinel.master=mymaster #spring.redis.sentinel.nodes=192.168.210.**\:26379 redis.proxyIpDBNum=15

#以下是我设置的session和授权等信息的过期时间
#session share unit hours(设置成分钟方便测试)
session.timeout=3
#cacheTimeOut unit hours
cache.timeout=12
 

2.Application开启缓存

@SpringBootApplication
@EnableCaching //开启缓存
public class OneserviceManagerApplication {
    public static void main(String[] args) {
        SpringApplication.run(OneserviceManagerApplication.class, args);
    }
}

3.编写RedisConfig.java配置类,主要作用是对象序列化

package com.ch.oneservice.manager.config.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig extends CachingConfigurerSupport {

    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    /**
     * 获取RedisTemplate对象,处理Redis数据,并且进行最佳序列化
     * @return
     */
    @Bean(name="redisTemplate")
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        //手动序列化
        JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringRedisSerializer);
        template.setValueSerializer(jdkSerializationRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        template.setHashValueSerializer(jdkSerializationRedisSerializer);
        //连接Redis
        //jedisConnectionFactory.setDatabase(6);
        template.setConnectionFactory(redisConnectionFactory);
        template.afterPropertiesSet();
        return template;
    }


}

二:redis做shiro的session共享

1.RedisSessionDao的自定义实现(session的缓存处理)

package com.ch.evaluation.auth.shiro.cas;

import com.ch.evaluation.common.util.PropertityUtil;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @description:SessionDao自定义实现
 * @author: xia hua
 * @date: 2018年10月19日
 * @modify by wangwei  at 2018-10-19
 * 将redis中存储的session时间单位改成毫秒
 */
@SuppressWarnings("all")
public class RedisSessionDao extends AbstractSessionDAO {
    private final String PREFIX="shiro_redis_session:";
    private static Logger logger = LoggerFactory.getLogger(RedisSessionDao.class);
    private RedisTemplate redisTpl;

    @Override
    public void update(Session session) throws UnknownSessionException {
        if (session==null || session.getId() == null){
            logger.error("redis update session error:session or session id is null");
            return;
        }

        try {
            redisTpl.opsForValue().set(PREFIX+session.getId().toString(), session, PropertityUtil.getPropertity("session.timeout"), TimeUnit.HOURS);
        } catch (Exception e) {
            // TODO: handle exception
            logger.error(e.getMessage(), e);
            throw new UnknownSessionException(e);
        }
    }

    @Override
    public void delete(Session session) {
        // TODO Auto-generated method stub
        if (session==null || session.getId() == null){
            logger.error("redis delete session error:session or session id is null");
            return;
        }
        try {
            redisTpl.delete(PREFIX+session.getId().toString());
        } catch (Exception e) {
            // TODO: handle exception
            logger.error(e.getMessage(), e);
        }
    }

    @Override
    public Collection<Session> getActiveSessions() {
        // TODO Auto-generated method stub
        return (Collection<Session>) redisTpl.execute(new RedisCallback<Collection<Session>>() {
            @Override
            public Collection<Session> doInRedis(RedisConnection connection) throws DataAccessException {
                // TODO Auto-generated method stub
                Set<Session> sessions = new HashSet<Session>();
                Set keys = redisTpl.keys(PREFIX+"*");

                for(Object key : keys){
                    Session session=(Session) redisTpl.opsForValue().get(key);
                    sessions.add(session);
                }
//
//                for (Session session : sessions) {
//                    sessions.add(session);
//                }
                return sessions;
            }
        });
    }

    @Override
    protected Serializable doCreate(Session session) {
        // TODO Auto-generated method stub
        if (session==null){
            logger.error("redis create session error:session  is null");
            return null;
        }
        // TODO Auto-generated method stub
        Serializable sessionId = generateSessionId(session);
        assignSessionId(session, sessionId);
        redisTpl.opsForValue().set(PREFIX+sessionId.toString(), session, session.getTimeout()/1000, TimeUnit.SECONDS);
        return sessionId;
    }

    @Override
    protected Session doReadSession(Serializable sessionId) {
        if (sessionId == null){
            logger.error("redis read session error:sessionId is null");
            return null;
        }
        // TODO Auto-generated method stub
        Session session = null;
        try {
            session = (Session) redisTpl.opsForValue().get(PREFIX+sessionId);
        } catch (Exception e) {
            // TODO: handle exception
            logger.error(e.getMessage(), e);
        }
        return session;
    }

    public void setRedisTpl(RedisTemplate redisTpl) {
        this.redisTpl = redisTpl;
    }
}
View Code

1.1这里引用了一个工具类读取配置文件

package com.ch.evaluation.common.util;

import org.apache.log4j.chainsaw.Main;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class PropertityUtil {


    public static int getPropertity(String key){
        Properties properties = new Properties();
        ClassLoader load = Main.class.getClassLoader();
        InputStream is = load.getResourceAsStream("application.properties");
        try {
            properties.load(is);
            String value = properties.getProperty(key);
            int val = 0;
            if(value!=null){
               val = Integer.parseInt(value);
            }
            return val;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0;
    }


}
View Code

2.RedisCache的自定义实现(对权限和认证信息的缓存处理)

package com.ch.dataauthority.common.redis;

import com.ch.dataauthority.common.util.PropertityUtil;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Redis缓存类
 * Created by 005803 on 2017/10/12.
 */

public class RedisCache<K, V> implements Cache<K, V> {

    private RedisTemplate redisTemplate;

    private static final String PREFIX = "shiro_redis_cache:";

    public RedisCache(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public V get(K key) throws CacheException {
        return (V) redisTemplate.opsForValue().get(PREFIX + key);
    }

    @Override
    public V put(K key, V value) throws CacheException {
        redisTemplate.opsForValue().set(PREFIX + key, value, PropertityUtil.getPropertity("cache.timeout"), TimeUnit.HOURS);
        return value;
    }

    @Override
    public V remove(K key) throws CacheException {
        Object value = redisTemplate.opsForValue().get(PREFIX + key);
        redisTemplate.delete(PREFIX + key);
        return (V) value;
    }

    @Override
    public void clear() throws CacheException {
        redisTemplate.delete(keys());
    }

    @Override
    public int size() {
        return keys().size();
    }

    @Override
    public Set<K> keys() {
        Set keys = redisTemplate.keys(PREFIX + "*");
        return keys != null ? keys : Collections.<K>emptySet();
    }

    @Override
    public Collection<V> values() {
        Set<K> keys = keys();
        Collection<V> c = new HashSet<>();
        for (K key : keys) {
            c.add((V) redisTemplate.opsForValue().get(key));
        }
        return c;
    }

}
View Code

 

3.Redis缓存管理器的配置RedisCacheManager.java
package com.ch.oneservice.manager.common.redis;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * Redis缓存管理器
 * Created by wangwei on 2018/10/19.
 */
public class RedisCacheManager implements CacheManager {

    private RedisTemplate redisTemplate;

    private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<>();

    public void setRedisTemplate(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public <K, V> Cache<K, V> getCache(String name) throws CacheException {

        Cache cache = caches.get(name);
        if (cache == null) {
            cache = new RedisCache(redisTemplate);
            caches.put(name, cache);
        }

        return cache;
    }

}

4.在你自定义的shiro的realm中重写key的策略

public class ExtendCasRealm extends CasRealm {
    
    private static Logger LOGGER = LoggerFactory.getLogger(ExtendCasRealm.class);
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
         ......................
    }
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        ........................
    }
     ....................
     ..................
    @Override
    protected Object getAuthorizationCacheKey(PrincipalCollection principals) {
        return principals.getPrimaryPrincipal() + ":authorization";
    }

    @Override
    protected Object getAuthenticationCacheKey(PrincipalCollection principals) {
        return principals.getPrimaryPrincipal() + ":authentication";
    }

    @Override
    protected Object getAuthenticationCacheKey(AuthenticationToken token) {
        return token.getPrincipal() + ":authentication";
    }
}

5.基本上配置以上信息就可以用了,值得注意的是要在ShiroCasConfig中配置这些Bean的关联关系,记得session的获取方式有两种,一种是servlet的session一种是shiro默认的session管理器DefaultWebSessionManager ,我们要记得注入DefaultWebSessionManager 管理器,不然程序执行过程中可能会默认执行isServletContainerSessions方法导致抛出一个session类型的异常

贴一下ShiroCasConfig配置,具体自己看吧

package com.ch.oneservice.manager.config.shirocas;

import com.ch.oneservice.manager.auth.shiro.cas.ExtendCasRealm;
import com.ch.oneservice.manager.auth.shiro.cas.RedisSessionDao;
import com.ch.oneservice.manager.auth.shiro.filter.ExtendAuthorizationFilter;
import com.ch.oneservice.manager.auth.shiro.filter.ExtendCasFilter;
import com.ch.oneservice.manager.auth.shiro.filter.ExtendLogoutFilter;
import com.ch.oneservice.manager.auth.shiro.filter.MyShiroSSOFilter;
import com.ch.oneservice.manager.auth.shiro.service.IAuthorizationService;
import com.ch.oneservice.manager.common.constants.WebConstants;
import com.ch.oneservice.manager.common.redis.RedisCacheManager;
import org.apache.shiro.cas.CasSubjectFactory;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.filter.DelegatingFilterProxy;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;


/**
 * Created by sunyong - 20170906
 */
@Configuration
public class ShiroCasConfig {

    @Value("${cas.server.url}")
    private String casServerUrl;

    @Value("${shiro.cas-server}")
    private String casServerUrlPrefix;

    @Value("${shiro.server}")
    private String shiroServerUrlPrefix;

    @Value("${session.timeout}")
    private int sessionTimeout;

    private static final String CAS_FILTER_NAME = "casFilter";
    private static final String SHIRO_FILTER_NAME = "shiroFilter";
    private static final String AUTH_FILTER_NAME = "authFilter";
    private static final String LOGOUT_FILTER_NAME = "logoutFilter";

    /**
     * 该类可以保证实现了org.apache.shiro.util.Initializable接口的shiro对象的init或者是destory方法被自动调用,
     * 而不用手动指定init-method或者是destory-method方法
     * 注意:如果使用了该类,则不需要手动指定初始化方法和销毁方法,否则会出错
     * @return
     */
//    @Bean(name = "lifecycleBeanPostProcessor")
//    public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
//        return new LifecycleBeanPostProcessor();
//    }

    /**
     * 注册DelegatingFilterProxy(Shiro)
     */
    @Bean
    public FilterRegistrationBean<DelegatingFilterProxy> filterRegistrationBean() {
        FilterRegistrationBean<DelegatingFilterProxy> filterRegistration = new FilterRegistrationBean<DelegatingFilterProxy>();
        filterRegistration.setFilter(new DelegatingFilterProxy(SHIRO_FILTER_NAME));
        filterRegistration.addInitParameter("targetFilterLifecycle", "true");
        filterRegistration.setEnabled(true);
        filterRegistration.addUrlPatterns("/*");
        return filterRegistration;
    }

    /**
     * 下面两个配置主要用来开启shiro aop注解支持. 使用代理方式;所以需要开启代码支持;
     *
     * @return
     */
//    @Bean
//    @DependsOn("lifecycleBeanPostProcessor")
//    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
//        DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
//        daap.setProxyTargetClass(true);
//        return daap;
//    }

    /**
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(
            DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    /**
     * 会话管理器
     * @auth 011336
     * @DATE 2018/10/15
     * @return
     */
    @Bean(name = "sessionManager")
    public DefaultWebSessionManager getDefaultWebSessionManager(RedisSessionDao sessionDAO, RedisCacheManager redisCacheManager) {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setGlobalSessionTimeout(sessionTimeout);
        sessionManager.setDeleteInvalidSessions(true);
        //sessionManager.setSessionValidationSchedulerEnabled(true);
        sessionManager.setSessionDAO(sessionDAO);
        sessionManager.setCacheManager(redisCacheManager);
        // TODO simpleCookie
        return sessionManager;
    }

    /**
     * 实例化SecurityManager,该类是shiro的核心类
     *
     * @return
     */
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(ExtendCasRealm extendCasRealm,
                           DefaultWebSessionManager sessionManager, RedisCacheManager redisCacheManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(extendCasRealm);
        securityManager.setCacheManager(redisCacheManager);
        securityManager.setSessionManager(sessionManager);
        securityManager.setSubjectFactory(new CasSubjectFactory());
        return securityManager;
    }


    /**
     * RedisSessionDao
     * @auth 011336
     * @DATE 2018/10/15
     * @return
     */
    @Bean
    public RedisSessionDao getRedisSessionDao(RedisTemplate redisTemplate) {
        RedisSessionDao sessionDAO = new RedisSessionDao();
        sessionDAO.setRedisTpl(redisTemplate);
        return sessionDAO;
    }

    /**
     * redisCacheManager
     * @auth 011336
     * @DATE 2018/10/15
     * @return
     */
    @Bean
    public RedisCacheManager getRedisCacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisTemplate(redisTemplate);
        return redisCacheManager;
    }

   /* *//**
     * MyShiroSSOFilter
     * @auth 011336
     * @DATE 2018/10/15
     * @return
     */
    @Bean(name = "shiroSSOFilter")
    public MyShiroSSOFilter getMyShiroSSOFilter(DefaultWebSessionManager sessionManager,
                                                DefaultWebSecurityManager securityManager) {
        MyShiroSSOFilter myShiroSSOFilter = new MyShiroSSOFilter();
        myShiroSSOFilter.setSessionManager(sessionManager);
        myShiroSSOFilter.setSecurityManager(securityManager);
        return myShiroSSOFilter;
    }
    /**
     * 配置缓存
     *
     * @return
     */
   /* @Bean
    public MemoryConstrainedCacheManager getMemoryCacheManager() {
        MemoryConstrainedCacheManager memoryCacheManager = new MemoryConstrainedCacheManager();
        return memoryCacheManager;
    }*/

    /**
     * 配置Realm,由于我们使用的是CasRealm,所以已经集成了单点登录的功能
     *
     * @param authorizationService
     * @return
     */
    @Bean
    public ExtendCasRealm getExtendCasRealm(IAuthorizationService authorizationService,
                                            RedisCacheManager redisCacheManager ) {
        ExtendCasRealm extendCasRealm = new ExtendCasRealm();
        extendCasRealm.setAuthorizationService(authorizationService);
        // cas登录服务器地址前缀
        extendCasRealm.setCasServerUrlPrefix(casServerUrlPrefix);
        // 客户端回调地址,登录成功后的跳转地址(自己的服务地址)
        extendCasRealm.setCasService(shiroServerUrlPrefix + WebConstants.CAS_FILTER_URI);
        extendCasRealm.setCachingEnabled(true);
        extendCasRealm.setAuthenticationCachingEnabled(true);
        extendCasRealm.setAuthenticationCacheName("authenticationCache");
        extendCasRealm.setAuthorizationCachingEnabled(true);
        extendCasRealm.setAuthorizationCacheName("authorizationCache");
        extendCasRealm.setCacheManager(redisCacheManager);
        return extendCasRealm;
    }

    /**
     * 注册单点登出的listener
     *
     * @return
     */
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE) // 优先级需要高于Cas的Filter
    public ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> singleSignOutHttpSessionListener() {
        ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> bean = new ServletListenerRegistrationBean<SingleSignOutHttpSessionListener>();
        bean.setListener(new SingleSignOutHttpSessionListener());
        bean.setEnabled(true);
        return bean;
    }

    /**
     * 注册单点登出filter
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean<SingleSignOutFilter> singleSignOutFilter() {
        FilterRegistrationBean<SingleSignOutFilter> bean = new FilterRegistrationBean<SingleSignOutFilter>();
        bean.setName("singleSignOutFilter");
        bean.setFilter(new SingleSignOutFilter());
        bean.addUrlPatterns("/*");
        bean.setEnabled(true);
        return bean;
    }

    /**
     * CAS过滤器
     *
     * @return
     */
    //@Bean(name = CAS_FILTER_NAME)
    public ExtendCasFilter getExtendCasFilter() {
        ExtendCasFilter casFilter = new ExtendCasFilter();
        casFilter.setName(CAS_FILTER_NAME);
        casFilter.setEnabled(true);
        // String loginUrl = casServerUrlPrefix + "/login?service=" + shiroServerUrlPrefix + CAS_FILTER_URI;
        casFilter.setFailureUrl("/error/casfailure");
        casFilter.setExtendFailureUrl("/error/casfailure"); // 由于原failuserUrl为私有字段,在扩展类中不能获取到值
        return casFilter;
    }

    /**
     * extAuth Filter
     */
    //@Bean(name = AUTH_FILTER_NAME)
    public ExtendAuthorizationFilter getExtendAuthorizationFilter(
            IAuthorizationService authorizationService) {
        ExtendAuthorizationFilter extAuthFilter = new ExtendAuthorizationFilter();
        extAuthFilter.setName(AUTH_FILTER_NAME);
        extAuthFilter.setEnabled(true);
        extAuthFilter.setAuthorizationService(authorizationService);
        return extAuthFilter;
    }

    /**
     * extLogout Filter
     */
    //@Bean(name = LOGOUT_FILTER_NAME)
    public ExtendLogoutFilter getExtendLogoutFilter(IAuthorizationService authorizationService) {
        ExtendLogoutFilter extLogoutFilter = new ExtendLogoutFilter();
        extLogoutFilter.setName(LOGOUT_FILTER_NAME);
        extLogoutFilter.setEnabled(true);
        extLogoutFilter.setAuthorizationService(authorizationService);
        extLogoutFilter.setRedirectUrl(casServerUrl + "/logout?service=" + shiroServerUrlPrefix);
        return extLogoutFilter;
    }

    /**
     * 使用工厂模式,创建并初始化ShiroFilter
     *
     * @param securityManager
     * @param authorizationService
     * @return
     */
    @Bean(name = SHIRO_FILTER_NAME)
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager,
                                                            IAuthorizationService authorizationService) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        String loginUrl = casServerUrl + "/login?service=" + shiroServerUrlPrefix + WebConstants.CAS_FILTER_URI;
        shiroFilterFactoryBean.setLoginUrl(loginUrl);
        shiroFilterFactoryBean.setSuccessUrl("/");
        shiroFilterFactoryBean.setUnauthorizedUrl("/error/unauthorized");
        Map<String, Filter> filters = new HashMap<>();
        filters.put(CAS_FILTER_NAME, getExtendCasFilter());
        filters.put(LOGOUT_FILTER_NAME, getExtendLogoutFilter(authorizationService));
        filters.put(AUTH_FILTER_NAME, getExtendAuthorizationFilter(authorizationService));
        shiroFilterFactoryBean.setFilters(filters);

        loadShiroFilterChain(shiroFilterFactoryBean);
        return shiroFilterFactoryBean;
    }

    private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean) {
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put(WebConstants.CAS_FILTER_URI, CAS_FILTER_NAME);
        filterChainDefinitionMap.put("/logout", LOGOUT_FILTER_NAME);
        filterChainDefinitionMap.put("/static/**", "anon");
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/front/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/plugin/**", "anon");
        filterChainDefinitionMap.put("/home/**", "anon");
        filterChainDefinitionMap.put("/super", "anon");
        filterChainDefinitionMap.put("/super/login", "anon");
        filterChainDefinitionMap.put("/error/**", "anon");
        filterChainDefinitionMap.put("/**", AUTH_FILTER_NAME);
        //filterChainDefinitionMap.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    }
}
View Code

以上代码我进行了优化,详情可点击这里

三:nginx实现负载均衡  【常用命令点这里

首先我们把项目部署在两个节点上

192.168.43.96

192.168.43.98

记得要开启8080端口,否则无法访问,我已经在部署时去除了项目名称(具体方法不贴了,可以自行百度,也可以查看我的其他博客)

(后来同事测试功能的时候,发现有一个节点挂掉了但nginx任然在往这个节点上负载请求,是不是很坑?其实是因为他部属的时候没有去除项目名称,而我在nginx中只配置了端口号,所以当请求负载到我上面部属的两个节点的时候就能访问数据,负载到他部属的节点的时候就请求不到数据。而且这个时候nginx认为他部属的这个节点是没有挂掉的)

然后要注意的是项目要把单点登录的回调地址改成ngnix的地址,如下配置:

注意:采用nginx做反向代理之后,浏览器、单点登录服务器就都是和nginx打交道了,我们实际部署项目的96、98两个节点对外界是透明的。

同时注意区分80和8080不是同一个端口,所以我们原先配置的回调地址要改为nginx的80端口;

单节点是的配置:
#application.url=http://192.168.43.96:8080 //原先配置
#application.url=http://192.168.43.96:8080  //原先配置

使用nginx后,每个节点上的回调地址都要改成nginx的地址加端口
application.url=http://192.168.43.97:80 //改成ngnix配置因为我的ngnix默认的是80端口 97为ngnix的地址

注意:最好不要在nginx服务器上部署tomcat服务,因为你的请求可能会直接访问到tomcat服务器而不经过ngnix,可能是我没有配置好,我在把他们部署在一台服务器上的时候遇到了每次请求sessionID都会变化的情况

然后就一直报错。具体原因还没明白,有大神知道的话,可以在文档下方留言

2.ngnix的安装就不贴了,可自行百度,我们主要讲一下最简单的配置让你的项目跑起来

可通过find / -name ngnix 命令查找ngnix的位置

然后切换到conf目录编辑ngnix.conf文件,详细配置说明可百度

cd nginx/conf/ngnix.conf

直接修改如下配置即可

    upstream tomcats {
        server 192.168.43.96:8080;//项目位置
        server 192.168.43.97:8080;//项目位置
    }

    server {
        listen       80;//默认80端口
        server_name  nginx-ww;//随意写

        #charset koi8-r;
............


      location / {
        proxy_pass http://tomcats;//指定路由为我们配置的项目位置
      }

3.启动nginx[重启等命令点这里]

cd usr/local/nginx/sbin
./nginx

可通过以下命令查看启动状态ps -ef | grep nginx   说明启动成功

[root@yjy-pt02 nginx]# ps -ef | grep nginx
root      4669     1  0 01:12 ?        00:00:00 nginx: master process ./nginx
nobody    4670  4669  0 01:12 ?        00:00:00 nginx: worker process
root      5086  3145  0 02:41 pts/0    00:00:00 grep nginx
[root@yjy-pt02 nginx]# 

最后查看成果

1.浏览器输入nginx地址 http://192.168.43.98

2.回车就会跳转到单点登录地址然后输入用户名密码校验通过就可以

3.由于nginx默认采用weight轮询的方式负载服务

所以我们在点击页面是可以看到两个服务器的日志输出情况

tail -f catalina.out 

可以发现日志轮流输出,说明负载实现,

我们也可以通过redis客户端查看权限缓存的信息

浏览器的cookie

 

redis信息

 

 

 

posted @ 2018-10-19 18:48  隔壁w王叔叔  阅读(4066)  评论(0编辑  收藏  举报