2011-04-17 5 views

Répondre

14

Printemps-sécurité a une telle configuration. see here pour savoir comment le faire. En bref - vous forcez le canal à utiliser https:

<http> 
    <intercept-url pattern="/secure/**" access="ROLE_USER" 
     requires-channel="https"/> 
    <intercept-url pattern="/**" access="ROLE_USER" 
     requires-channel="any"/> 
</http> 

Si vous ne souhaitez pas utiliser-sécurité au printemps, voici un intercepteur que j'ai écrit:

@Component 
public class SslInterceptor extends HandlerInterceptorAdapter { 

    // no need to inject it for now.. 
    private PathMatcher pathMatcher = new AntPathMatcher(); 

    @Value("${base.url.secure}") 
    private String secureRoot; 

    @Resource(name="secureLocations") 
    private List<String> secureLocations; 

    @Value("${use.ssl}") 
    private boolean useSsl; 


    @Override 
    public boolean preHandle(HttpServletRequest request, 
      HttpServletResponse response, Object handler) throws Exception { 

     if (useSsl && !request.isSecure() && shouldForceSecure(request.getRequestURI())) { 

      String redirectUrl = secureRoot + request.getRequestURI(); 
      if (request.getQueryString() != null) { 
       redirectUrl += "?" + request.getQueryString(); 
      } 
      // force session creation - thus it will be accessible to both the 
      // secure and the insecure contexts 
      request.getSession(true); 
      response.sendRedirect(redirectUrl); 
      return false; 
     } 

     return true; 
    } 

    private boolean shouldForceSecure(String path) { 
     for (String pattern : secureLocations) { 
      if (pathMatcher.match(pattern, path)) { 
       return true; 
      } 
     } 
     return false; 
    } 
} 
+0

Merci Bozho. L'exemple est superbe. Pouvez-vous également partager avec moi comment cela peut être fait en utilisant la configuration de sécurité de printemps. –

+0

voir mis à jour .... – Bozho

+0

Exactement ce que je veux. En fait, j'ai vu cet article avant de poster la question. Je suis nouveau à Spring MVC. J'ai mis dans le fichier de configuration du printemps, mais je recevais des erreurs d'analyse. Je sais que je demande trop, mais pouvez-vous me donner un exemple de fichier XML? Merci Bozho. –

1

Vous pouvez le faire dans votre configuration Tomcat.

essayez d'ajouter redirectPort = "" dans le fichier server.xml au connecteur HTTP.

Espérons que ça aide.

Mise à jour:

Cet article vous expliquera comment traiter avec SSL et a beaucoup d'un exemple.

http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html

+0

Eh bien, il aide que si elles utilisent tomcat ... – skaffman

+0

D'accord, mais chaque serveur d'application a de telles options même IIS :). Je viens d'écrire l'idée de ce qui devrait être fait. –

+0

S'il vous plaît pouvez-vous donner un exemple –

2

Pour une approche d'annotation sans la sécurité du printemps, j'ai écrit un intercepteur et une nouvelle annotation:

/** 
* Request mapping annotation to enforce secure or insecure requests. 
* Per default the annotated mapping is enforced to be secure. 
* 
* @see org.springframework.web.bind.annotation.RequestMapping 
*/ 
@Target({ElementType.METHOD, ElementType.TYPE}) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
@Mapping 
public @interface RequestProtocol { 

    boolean secure() default true; 
} 

vous pouvez donc simplement déclarer (ici pour REST) ​​méthode de commande comme ceci:

@RequestMapping(value = "/secret", method = RequestMethod.GET) 
@RequestProtocol(secure = true) 
@ResponseBody 
public Result doSecure(@Valid Model model) { 
    return doSomething(model)); 
} 

Pour activer le mappage, utilisez un intercepteur redirigeant sur le mauvais protocole. Vous pouvez également effectuer une manipulation plus simple en envoyant simplement une réponse INTERDITE.

/** 
* Interceptor to send a redirect on security enforced mappings with wrong type of request. 
* 
* @see RequestProtocol 
*/ 
class RequestProtocolInterceptor extends HandlerInterceptorAdapter { 

    private static final int PORT_DIFF = 443 - 80; 

    @Override 
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { 
    Boolean secure = checkSecure(handler); 
    if (secure != null && request.isSecure() != secure) { 
     response.sendRedirect(switchSecure(secure, request.getRequestURL())); 
     return false; 
    } 
    return true; 
    } 

    private Boolean checkSecure(Object handler) { 
    if (handler instanceof HandlerMethod) { 
     HandlerMethod method = (HandlerMethod)handler; 
     RequestProtocol annotation = method.getMethodAnnotation(RequestProtocol.class); 
     if (annotation == null) { 
     annotation = AnnotationUtils.findAnnotation(method.getBeanType(), RequestProtocol.class); 
     } 
     return annotation == null ? null : annotation.secure(); 
    } 
    return null; 
    } 

    private String switchSecure(boolean secure, StringBuffer url) { 
    int endSchema = url.indexOf("://"); 
    url.replace(0, endSchema, secure ? "https" : "http"); 
    int startPort = url.indexOf(":", endSchema + 3); 
    if (startPort != -1) { 
     int endPort = url.indexOf("/", startPort); 
     int port = Integer.parseInt(url.substring(startPort + 1, endPort)); 
     port += secure ? PORT_DIFF : -PORT_DIFF; 
     url.replace(startPort + 1, endPort, String.valueOf(port)); 
    } 
    return url.toString(); 
    } 
} 

Pour activer l'intercepteur sur une annotation pure à partir de config Spring, utilisez le WebMvcConfigurerAdapter:

@Configuration 
@EnableWebMvc 
public class MyConfiguration extends WebMvcConfigurerAdapter { 

    @Override 
    public void addInterceptors(InterceptorRegistry registry) { 
    registry.addInterceptor(new RequestProtocolInterceptor()); 
    } 
}