2017-12-06 40 views
8

मैं एक आरईएसटी सेवा विकसित कर रहा हूं। यह JSON का उपयोग करता है और किसी समस्या के मामले में कुछ पूर्वनिर्धारित JSON ऑब्जेक्ट को वापस करना होगा। डिफ़ॉल्ट स्प्रिंग प्रतिक्रिया इस प्रकार है:वसंत एमवीसी (या वसंत बूट)। सुरक्षा संबंधी अपवादों के लिए कस्टम JSON प्रतिक्रिया 401 अनधिकृत या 403 निषिद्ध)

{ 
    "timestamp": 1512578593776, 
    "status": 403, 
    "error": "Forbidden", 
    "message": "Access Denied", 
    "path": "/swagger-ui.html" 
} 

मैं एक दम से एक (एक स्टैकट्रेस और अतिरिक्त अपवाद संबंधित जानकारी के साथ) के साथ इस डिफ़ॉल्ट JSON बदलना चाहते हैं।

वसंत डिफ़ॉल्ट व्यवहार को ओवरराइट करने का एक आसान तरीका प्रदान करता है। एक कस्टम अपवाद हैंडलर के साथ @RestControllerAdvice बीन को परिभाषित करना चाहिए। जैसा इस

@RestControllerAdvice 
public class GlobalExceptionHandler { 
    @ExceptionHandler(value = {Exception.class}) 
    public ResponseEntity<ExceptionResponse> unknownException(Exception ex) { 
    ExceptionResponse resp = new ExceptionResponse(ex, level); // my custom response object 
    return new ResponseEntity<ExceptionResponse>(resp, resp.getStatus()); 
    } 
    @ExceptionHandler(value = {AuthenticationException.class}) 
    public ResponseEntity<ExceptionResponse> authenticationException(AuthenticationExceptionex) { 
     // WON'T WORK 
    } 
} 

कस्टम ExceptionResponse वस्तु तो एक विशेष संदेश कनवर्टर का उपयोग कर स्प्रिंग द्वारा JSON में परिवर्तित हो जाएगा।

समस्या है, InsufficientAuthenticationException की तरह है कि सुरक्षा अपवाद एक विधि @ExceptionHandler के रूप में एनोटेट द्वारा रोक नहीं किया जा सकता। वसंत एमवीसी प्रेषक सर्वलेट दर्ज किए जाने से पहले इस तरह के अपवाद होते हैं और सभी एमवीसी हैंडलर शुरू किए गए थे।

कस्टम फ़िल्टर का उपयोग करके इस अपवाद को रोकना और स्क्रैच से अपना JSON क्रमबद्धता बनाना संभव है। इस मामले में किसी को एक कोड मिलेगा जो वसंत एमवीसी बुनियादी ढांचे के बाकी हिस्सों से पूरी तरह से स्वतंत्र है। यह अच्छा नहीं है।

मुझे मिला समाधान मैं काम करता प्रतीत होता है, लेकिन यह पागल लग रहा है।

@Configuration 
public class CustomSecurityConfiguration extends 
WebSecurityConfigurerAdapter { 

@Autowired 
protected RequestMappingHandlerAdapter requestMappingHandlerAdapter; 

@Autowired 
protected GlobalExceptionHandler exceptionHandler; 

@Override 
protected void configure(HttpSecurity http) throws Exception { 

    http.authorizeRequests() 
     .anyRequest() 
     .fullyAuthenticated(); 

    http.exceptionHandling() 
     .authenticationEntryPoint(authenticationEntryPoint()); 
} 

public AuthenticationEntryPoint authenticationEntryPoint() { 
    return new AuthenticationEntryPoint() { 
     @Override 
     public void commence(HttpServletRequest request, HttpServletResponse response, 
       AuthenticationException authException) throws IOException, ServletException { 

      try { 
       ResponseEntity<ExceptionResponse> objResponse = exceptionHandler.authenticationException(authException); 

       Method unknownException = exceptionHandler.getClass().getMethod("authenticationException", AuthenticationException.class); 

       HandlerMethod handlerMethod = new HandlerMethod(exceptionHandler, unknownException); 

       MethodParameter returnType = handlerMethod.getReturnValueType(objResponse); 

       ModelAndViewContainer mvc = new ModelAndViewContainer(); // not really used here. 

       List<HttpMessageConverter<?>> mconverters = requestMappingHandlerAdapter.getMessageConverters(); 

       DispatcherServletWebRequest webRequest = new DispatcherServletWebRequest(request, response); 

       HttpEntityMethodProcessor processor = new HttpEntityMethodProcessor(mconverters); 

       processor.handleReturnValue(objResponse, returnType, mvc, webRequest); 
      } catch (IOException e) { 
       throw e; 
      } catch (RuntimeException e) { 
       throw e;      
      } catch (Exception e) { 
       throw new ServletException(e); 
      } 
     } 
    }; 
} 

वहाँ (वसंत के साथ, संदेश कन्वर्टर्स में निर्माण MIME प्रारूप बातचीत आदि) वसंत क्रमबद्धता पाइप का उपयोग करने के जो इस की तुलना में बेहतर लग रहा है कोई तरीका है?

+0

यहां कुछ और अधिक सुरुचिपूर्ण समाधान है, जो आपके जैसे ही हैं, लेकिन मूल अपवाद को अपवाद में लपेटना है जो @ExceptionHandler द्वारा "कैच" करने की अनुमति देता है: https://stackoverflow.com/questions/43632565/exceptionhandler-for- एक प्री-कंट्रोलर-फ़िल्टर-वसंत-सुरक्षा/43636386 – spekdrum

+0

http://www.baeldung.com/spring-security-custom-access-denied-page –

उत्तर

0

स्प्रिंग बाहर के बॉक्स अपवाद AccessDeniedHandler के माध्यम से निपटने के लिए समर्थन है, जो नीचे दिए गए चरणों का अनुसरण करने में AccessDeniedException यानी HTTP 403

के मामले में एक कस्टम JSON प्रतिक्रिया प्राप्त करने के लिए नीचे दिए गए जैसे एक कस्टम हैंडलर कुछ को लागू करें द्वारा उपयोग किया जा सकता प्रदान करते हैं

public class CustomAccessDeniedHandler implements AccessDeniedHandler { 

    @Override 
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException exc) 
     throws IOException, ServletException { 
     System.out.println("Access denied .. "); 
     // do something 
     response.sendRedirect("/deny"); 
    } 
} 

अगला config में इस हैंडलर के एक सेम बना सकते हैं और सुरक्षा अपवाद संचालक (महत्वपूर्ण नोट वसंत के यह आपूर्ति - /deny बाहर करने के लिए सुनिश्चित प्रमाणीकरण से किसी और अनुरोध असीम त्रुटि)

@Bean 
public AccessDeniedHandler accessDeniedHandler(){ 
    return new CustomAccessDeniedHandler(); 
} 

@Override 
protected void configure(HttpSecurity http) throws Exception { 
    http.cors().and() 
      // some other configuration 
      .antMatchers("/deny").permitAll() 
      .and() 
      .exceptionHandling().accessDeniedHandler(accessDeniedHandler()); 
} 

नियंत्रक कक्षा में अगले एक हैंडलर लिखना /deny करने के लिए इसी को हल करने पर रखेंगे और बस SomeException का एक नया उदाहरण (या किसी अन्य Exception के रूप में उपयुक्त फेंक), जो होगा @RestControllerAdvice संबंधित हैंडलर में अवरुद्ध किया जाना चाहिए।

@GetMapping("/deny") 
public void accessDenied(){ 
    throw new SomeException("User is not authorized"); 
} 

यदि कोई और जानकारी आवश्यक है तो टिप्पणियों में जानें।

0

मुझे लगता है कि अगली कॉन्फ़िगरेशन काम करनी चाहिए, कृपया इसे आज़माएं।

@Autowired 
private HandlerExceptionResolver handlerExceptionResolver; 

public AuthenticationEntryPoint authenticationEntryPoint() { 
    return new AuthenticationEntryPoint() { 
     @Override 
     public void commence(HttpServletRequest request, HttpServletResponse response, 
          AuthenticationException authException) throws IOException, ServletException { 

      try { 
       handlerExceptionResolver.resolveException(request, response, null, authException); 
      } catch (RuntimeException e) { 
       throw e; 
      } catch (Exception e) { 
       throw new ServletException(e); 
      } 
     } 
    }; 
} 
1

बीन कक्षा

@Component public class AuthenticationExceptionHandler implements AuthenticationEntryPoint, Serializable 

बनाएँ और commence() method ओवरराइड और उदाहरण नीचे

ObjectMapper mapper = new ObjectMapper(); 
String responseMsg = mapper.writeValueAsString(responseObject); 
response.getWriter().write(responseMsg); 

और SecurityConfiguration कक्षा में @Autowire AuthenticationExcetionHandler की तरह वस्तु नक्शाकार का उपयोग कर json प्रतिक्रिया बना सकते हैं और configure(HttpSecurity http) method में लाइनों

नीचे जोड़ने
 http.exceptionHandling() 
      .authenticationEntryPoint(authenticationExceptionHandler) 

इस तरह आप custome json प्रतिक्रिया 401/403 भेजने में सक्षम होना चाहिए। ऊपर जैसा ही आप AccessDeniedHandler का उपयोग कर सकते हैं। अगर हमें समस्या हल करने में मदद मिली तो हमें बताएं।

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