2011-04-17 110 views

回答

14

春季安全具有这样的配置。 see here如何做到这一点。总之 - 你强制通道使用https:

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

如果你不想使用Spring的安全,下面是我写的拦截:

@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

感谢Bozho。这个例子看起来不错。你能否也请与我分享如何使用弹簧安全配置来完成这项工作。 – 2011-04-17 09:19:16

+0

看到更新.... – Bozho 2011-04-17 09:23:46

+0

正是我想要的。事实上,我在发布问题之前看过这篇文章。我是Spring MVC的新手。我把弹簧配置文件,但我得到解析错误。我知道我问得太多,但你能给我一个示例XML文件吗?谢谢Bozho。 – 2011-04-17 09:31:56

1

您可以在Tomcat配置中执行此操作。

尝试将server.xml中的redirectPort =“”添加到HTTP连接器。

希望它有帮助。

更新:

本文将解释你如何处理SSL,有很多的例子。

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

+0

那么它只有帮助,如果他们使用Tomcat ... – skaffman 2011-04-17 08:52:47

+0

同意,但每个应用服务器这样的选项甚至IIS :)。我只是写了这个想法应该做什么。 – 2011-04-17 08:54:32

+0

请你可以提供一个例子 – 2011-04-17 08:54:42

2

对于注释为基础的方法,而不春天的安全我写了一个拦截器和一个新的注解:像这样

/** 
* 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; 
} 

所以,你可以简单地声明(这里REST)控制器的方法:

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

要启用映射,请使用拦截器重定向错误的协议。您也可以通过发送FORBIDDEN响应来进行更简单的处理。

/** 
* 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(); 
    } 
} 

要启用一个纯粹的基于注释的Spring配置的拦截器,使用WebMvcConfigurerAdapter:

@Configuration 
@EnableWebMvc 
public class MyConfiguration extends WebMvcConfigurerAdapter { 

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