2015-09-25 7 views
5

के साथ सत्र निर्माण पर सत्र को दोहराया नहीं गया है। मैं स्प्रिंग क्लाउड के जुउल, यूरेका और मेरी अपनी सेवाओं का उपयोग करके एक माइक्रोस्कोस आर्किटेक्चर को कार्यान्वित करने का प्रयास कर रहा हूं। मेरे पास कई सेवाएं हैं जिनमें यूआई और सेवाएं हैं और प्रत्येक x50 9 सुरक्षा का उपयोग कर उपयोगकर्ताओं को प्रमाणित कर सकता है। अब मैं उन सेवाओं के सामने जुउल लगाने की कोशिश कर रहा हूं। चूंकि जुउल बैकएंड में क्लाइंट केर्ट्स को अग्रेषित नहीं कर सकता है, इसलिए मैंने सोचा कि अगली सबसे अच्छी बात यह है कि उपयोगकर्ता को ज़ूउल के सामने वाले दरवाजे पर प्रमाणित करना होगा, फिर बैकएंड सेवाओं में अपने प्रमाणीकृत राज्य को दोहराने के लिए वसंत सत्र का उपयोग करें। मैंने डेव सीयर से ट्यूटोरियल here का पालन किया है और यह लगभग काम करता है, लेकिन पहले अनुरोध पर नहीं। यहां मेरा मूल सेटअप है:स्प्रिंग बूट, सत्र, और रेडिस

  • जुआल प्रॉक्सी बैकएंड सेवाओं के मार्ग पर सेट करने के लिए अपने स्वयं के एप्लिकेशन में सेट है। क्या स्प्रिंग सुरक्षा x509 ऑथ करने में सक्षम है। उपयोगकर्ताओं को सफलतापूर्वक लेखित करता है। @EnableRedisHttpSession
  • बैकएंड सेवा के साथ वसंत सत्र भी वसंत सुरक्षा सक्षम है। मैंने यहां x509 को सक्षम/अक्षम करने की कोशिश की है, लेकिन हमेशा उपयोगकर्ता को विशिष्ट अंतराल के लिए प्रमाणीकृत करने की आवश्यकता होती है। वसंत सत्र और @EnableRedisHttpSession का भी उपयोग करता है।

यदि आप सभी सत्रों को साफ़ करते हैं और ताजा शुरू करते हैं और प्रॉक्सी को हिट करने का प्रयास करते हैं, तो यह zuul सर्वर के प्रमाणपत्र का उपयोग करके बैकएंड को अनुरोध भेजता है। बैकएंड सेवा तब उपयोगकर्ता को उस उपयोगकर्ता प्रमाण के आधार पर देखती है और सोचती है कि उपयोगकर्ता सर्वर है, न कि उपयोगकर्ता जो जुउल प्रॉक्सी में प्रमाणित था। यदि आप केवल पृष्ठ को रीफ्रेश करते हैं, तो आप अचानक बैक एंड पर सही उपयोगकर्ता बन जाते हैं (उपयोगकर्ता Zuul प्रॉक्सी में प्रमाणित)। जिस तरह से मैं जांच कर रहा हूं वह प्रिंसिपल उपयोगकर्ता को बैकएंड नियंत्रक में प्रिंट करना है। तो पहले अनुरोध पर, मैं सर्वर उपयोगकर्ता देखता हूं, और दूसरे अनुरोध पर, मैं वास्तविक उपयोगकर्ता को देखता हूं। अगर मैं बैक एंड पर x509 को अक्षम करता हूं, तो पहले अनुरोध पर, मुझे 403 मिल जाता है, फिर रीफ्रेश पर, यह मुझे अंदर देता है।

ऐसा लगता है कि सत्र बैकएंड को पर्याप्त तेज़ी से दोहराया नहीं गया है, जब उपयोगकर्ता अगली कड़ी में प्रमाणित है, इसने ज्यूल के अनुरोध के बाद इसे बैकएंड में नहीं बनाया है।

क्या सत्र की गारंटी देने का कोई तरीका है पहले अनुरोध (यानी सत्र निर्माण) पर दोहराया गया है? या क्या यह सुनिश्चित करने के लिए एक कदम लापता है कि यह सही तरीके से काम करता है?

Zuul प्रॉक्सी::

@SpringBootApplication 
@Controller 
@EnableAutoConfiguration 
@EnableZuulProxy 
@EnableRedisHttpSession 
public class ZuulEdgeServer { 
    public static void main(String[] args) { 
     new SpringApplicationBuilder(ZuulEdgeServer.class).web(true).run(args); 
    } 
} 

Zuul कॉन्फ़िग:

info: 
    component: Zuul Server 

endpoints: 
    restart: 
    enabled: true 
    shutdown: 
    enabled: true 
    health: 
    sensitive: false 

zuul: 
    routes: 
    service1: /** 

logging: 
    level: 
    ROOT: INFO 
# org.springframework.web: DEBUG 
    net.acesinc: DEBUG 

security.sessions: ALWAYS 
server: 
    port: 8443 
    ssl: 
     key-store: classpath:dev/localhost.jks 
     key-store-password: thepassword 
     keyStoreType: JKS 
     keyAlias: localhost 
     clientAuth: want 
     trust-store: classpath:dev/localhost.jks 

ribbon: 
    IsSecure: true 

बैकएंड सेवा:

@SpringBootApplication 
@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class, ThymeleafAutoConfiguration.class, org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration.class }) 
@EnableEurekaClient 
@EnableRedisHttpSession 
public class Application { 

    public static void main(String[] args) { 
     SpringApplication.run(Application.class, args); 
    } 
} 

बैकएंड सेवा कॉन्फ़िग

यहाँ महत्वपूर्ण कोड के टुकड़े में से कुछ हैं :

spring.jmx.default-domain: ${spring.application.name} 

server: 
    port: 8444 
    ssl: 
     key-store: classpath:dev/localhost.jks 
     key-store-password: thepassword 
     keyStoreType: JKS 
     keyAlias: localhost 
     clientAuth: want 
     trust-store: classpath:dev/localhost.jks 

#Change the base url of all REST endpoints to be under /rest 
spring.data.rest.base-uri: /rest 

security.sessions: NEVER 

logging: 
    level: 
    ROOT: INFO 
# org.springframework.web: INFO 
# org.springframework.security: DEBUG 
    net.acesinc: DEBUG 

eureka: 
    instance: 
    nonSecurePortEnabled: false 
    securePortEnabled: true 
    securePort: ${server.port} 
    homePageUrl: https://${eureka.instance.hostname}:${server.port}/ 
    secureVirtualHostName: ${spring.application.name} 

बैकएंड नियंत्रकों में से एक: वर्तमान में डेटा स्टोर करने के लिए लिखता है जब अनुरोध के लिए प्रतिबद्ध है

@Controller 
public class SecureContent1Controller { 
    private static final Logger log = LoggerFactory.getLogger(SecureContent1Controller.class); 

    @RequestMapping(value = {"/secure1"}, method = RequestMethod.GET) 
    @PreAuthorize("isAuthenticated()") 
    public @ResponseBody String getHomepage(ModelMap model, Principal p) { 
     log.debug("Secure Content for user [ " + p.getName() + " ]"); 
     model.addAttribute("pageName", "secure1"); 
     return "You are: [ " + p.getName() + " ] and here is your secure content: secure1"; 
    } 
} 
+1

हाय एंड्रयू, आपकी समस्या का समाधान किसी अन्य प्रश्न में वर्णित है http://stackoverflow.com/questions/34751700/spring-zuul-api-gateway-with-spring-ession-redis-authenticate-and-route-in -sa? rq = 1 # answer-38867506 – shobull

+0

बहुत बढ़िया! लगता है यह काम कर रहा है! मेरे पास पहले से ही उस समाधान का आधा था, और सोचा कि मैंने दूसरे भाग की कोशिश की थी, लेकिन मुझे लगता है कि यह अब काम नहीं कर रहा है! इसे इंगित करने के लिए फिर से धन्यवाद! –

उत्तर

2

इस समस्या के लिए मुझे Justin Taylor's answer पर इंगित करने के लिए shobull के लिए धन्यवाद। पूर्णता के लिए, मैं यहां पूरा जवाब भी देना चाहता था। यह एक दो भाग समाधान है:

  1. वसंत सत्र बेसब्री से प्रतिबद्ध हैं - के बाद से वसंत सत्र v1.0 वहाँ एनोटेशन संपत्ति @EnableRedisHttpSession(redisFlushMode = RedisFlushMode.IMMEDIATE) जो तुरंत Redis में सत्र डेटा बचाता है। दस्तावेज़ीकरण here। वर्तमान अनुरोध के हेडर में सत्र जोड़ने के लिए
  2. सरल Zuul फिल्टर:

    import com.netflix.zuul.ZuulFilter; 
    import com.netflix.zuul.context.RequestContext; 
    import javax.servlet.http.HttpSession; 
    import org.slf4j.Logger; 
    import org.slf4j.LoggerFactory; 
    import org.springframework.beans.factory.annotation.Autowired; 
    import org.springframework.session.Session; 
    import org.springframework.session.SessionRepository; 
    import org.springframework.stereotype.Component; 
    
    @Component 
    public class SessionSavingZuulPreFilter extends ZuulFilter { 
        @Autowired 
        private SessionRepository repository; 
    
        private static final Logger log = LoggerFactory.getLogger(SessionSavingZuulPreFilter.class); 
    
        @Override 
        public String filterType() { 
         return "pre"; 
        } 
    
        @Override 
        public int filterOrder() { 
         return 1; 
        } 
    
        @Override 
        public boolean shouldFilter() { 
         return true; 
        } 
    
        @Override 
        public Object run() { 
         RequestContext context = RequestContext.getCurrentContext(); 
    
         HttpSession httpSession = context.getRequest().getSession(); 
         Session session = repository.getSession(httpSession.getId()); 
    
         context.addZuulRequestHeader("Cookie", "SESSION=" + httpSession.getId()); 
    
         log.trace("ZuulPreFilter session proxy: {}", session.getId()); 
    
         return null; 
        } 
    } 
    

इन दोनों अपने Zuul प्रॉक्सी भीतर होना चाहिए।

0

वसंत सत्र समर्थन करते हैं। यह एक ही समय में सभी विशेषताओं को लिखकर "चैट ट्रैफिक" को कम करने का प्रयास करना है।

यह पहचाना जाता है कि यह कुछ परिदृश्यों (जैसे आप सामना कर रहे हैं) के लिए आदर्श नहीं है। इनके लिए हमारे पास spring-session/issues/250 है।वर्कअराउंड RedisOperationsSessionRepository की प्रतिलिपि बनाना है और saveDelta किसी भी समय संपत्ति बदल दी गई है।

+0

मुझे लगता है कि आप का शाब्दिक अर्थ है "प्रतिलिपि" RedisOperationsSessionRepository क्योंकि RedisSession को ओवरराइड नहीं किया जा सकता है? साथ ही, सहेजने के लिए लिंक करने की कोशिश की गई लाइन संख्या मौजूद नहीं है। मुझे लगता है कि आप setAttribute() विधि के अंत में कॉल saveDelta का मतलब है? और फिर, क्या आप डिफ़ॉल्ट रूप से ओवरराइड करने के लिए केवल RedisOperationsSessionRepository प्रकार का एक बीन पंजीकृत करते हैं? –

संबंधित मुद्दे