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信息

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM