2016-07-02 7 views
0

Я пытаюсь добавить токен CSRF в Spring Session redis, так как нужно запустить webapp в кластере.Значок CSRF в redis spring session

решение Потребность как на Spring Java конфигурации/XML (для старой версии)

И я уже использую RedisHttpSessionConfiguration для сессионной части (реализовали в первой фазе)

Мой WebSecurityConfig является

package com.groupon.website.config; 

import javax.servlet.FilterRegistration; 

import org.apache.logging.log4j.LogManager; 
import org.apache.logging.log4j.Logger; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.core.annotation.Order; 
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 
import org.springframework.security.web.csrf.CsrfTokenRepository; 
import org.springframework.security.web.util.matcher.RequestMatcher; 

@EnableWebSecurity 
@Configuration 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 

private Logger logger = LogManager.getLogger(WebSecurityConfig.class); 
@Autowired 
@Qualifier("csrfSecurityRequestMatcher") 
RequestMatcher csrfSecurityRequestMatcher; 

@Autowired 
@Qualifier("redisCsrfTokenRepository") 
private CsrfTokenRepository redisCsrfTokenRepository; 

@Override 
protected void configure(HttpSecurity http) throws Exception { 
    logger.info("Inside WebSecurityConfig"); 

    //403 issue 


    http.headers().xssProtection().and().csrf().requireCsrfProtectionMatcher(csrfSecurityRequestMatcher) 
      .csrfTokenRepository(redisCsrfTokenRepository) 
     ; 

    } 

    } 

И CsrfTokenRepository является RedisCsrfTokenRepository

package com.groupon.website.config; 


import java.util.UUID; 

import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import javax.servlet.http.HttpSession; 

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.beans.factory.InitializingBean; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.beans.factory.annotation.Value; 
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; 
import org.springframework.security.web.csrf.CsrfToken; 
import org.springframework.security.web.csrf.CsrfTokenRepository; 
import org.springframework.security.web.csrf.DefaultCsrfToken; 
import org.springframework.session.ExpiringSession; 
import org.springframework.session.data.redis.RedisOperationsSessionRepository; 
import org.springframework.stereotype.Component; 
import org.springframework.util.SerializationUtils; 

import redis.clients.jedis.Jedis; 

@Component 
public class RedisCsrfTokenRepository implements   CsrfTokenRepository,InitializingBean { 

private static final Logger log =   LoggerFactory.getLogger(RedisCsrfTokenRepository.class); 

public static final String CSRF_PARAMETER_NAME = "_csrf"; 

public static final String CSRF_HEADER_NAME = "X-CSRF-TOKEN"; 

@Value("${redis.host.name}") 
private String redisHostName; 
@Value("${redis.port}") 
private int redisPort; 

private Jedis tokenRepository; 

@Autowired 
private JedisConnectionFactory jedisConnectionFactory; 

//@Autowired 
//private RedisOperationsSessionRepository sessionRepository; 


public RedisCsrfTokenRepository() { 
    log.info("Creating {}", RedisCsrfTokenRepository.class.getSimpleName()); 

} 

@Override 
public CsrfToken generateToken(HttpServletRequest request) { 
    return new DefaultCsrfToken(CSRF_HEADER_NAME, CSRF_PARAMETER_NAME, createNewToken()); 
} 

@Override 
public void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) { 
    String key = getKey(request); 
    if (key == null) 
     return; 

    if (token == null) { 
     //Use connection factory 
     //tokenRepository.del(key.getBytes()); 
     jedisConnectionFactory.getConnection().del(key.getBytes()); 
    } else { 
     //Use connection factory 
     //tokenRepository.set(key.getBytes(), SerializationUtils.serialize(token)); 
     jedisConnectionFactory.getConnection().set(key.getBytes(), SerializationUtils.serialize(token)); 
    } 

} 

@Override 
public CsrfToken loadToken(HttpServletRequest request) { 
    String key = getKey(request); 
    if (key != null) { 
     //Use connection factory 
     //byte[] tokenString = tokenRepository.get(key.getBytes()); 
     byte[] tokenString = jedisConnectionFactory.getConnection().get(key.getBytes()); 
     if (tokenString != null) { 
      return (CsrfToken) SerializationUtils.deserialize(tokenString); 
     } 
    } 
    return null; 
} 

private String getKey(HttpServletRequest request) { 

    //getKey going to be changed 
    HttpSession session = request.getSession(false); 
    //RedisOperationsSessionRepository sessionRepository = new RedisOperationsSessionRepository(redisConnectionFactory) 

    //ExpiringSession session = sessionRepository.getSession(request.getSession().getId()); 
    if (session == null) { 
     return null; 
    } 

    String result = session.getId()+CSRF_PARAMETER_NAME; 
    //String result = request.getHeader("X-CSRF-TOKEN"); 
    return result; 
} 

private String createNewToken() { 
    return UUID.randomUUID().toString(); 
} 

@Override 
public void afterPropertiesSet() throws Exception { 
    tokenRepository = new Jedis(redisHostName, redisPort, 30000); 
} 
} 

(tokenRpository не используется, я просто скопировать вставить код, как это, но jedisConnectionFatcory используется)

Я все еще получаю 403 прерывисто, чтобы показать, что маркер CSRF это не получается.

Показать только java config. Может кто-нибудь, пожалуйста, помогите мне с этим.

+0

@ dsyer Вы можете помочь здесь –

ответ

0

Мы решили, изменив нашу RedisCsrfTokenRepository, чтобы получить ключ от вместо

HttpSession session = request.getSession(false); 

мы используем

Cookie sessionCookies = WebUtil.getCookie (request, WebAppConstants.SESSION); 


if (sessionCookies == null || sessionCookies.getValue() == null) { 
    return null; 
} 

String sessionId = sessionCookies.getValue(); 

Потому что мы использовали печенье, который работал.

В конвейере, изменяя defaultSessionFilter, так что это изменение не требуется.

Смежные вопросы