我有一个运行多个WAR文件的tomcat实例。 tomcat实例被代理在Apache服务器后面,以便剥离上下文路径。相反,我正在使用子域名:
基本上,我的设置如下:
http://localhost:8080/app1 -> http://app1.example.com/
http://localhost:8080/app2 -> http://app2.example.com/
我需要做的是使所有重定向上下文相对,因为我不再在URL中包含上下文路径。我注意到Spring Security允许将重定向设置为" context related"使用默认类DefaultRedirectStrategy。为了使重定向工作正常,我必须覆盖多个对象,以便我可以简单地将默认的DefaultRedirectStrategy实例与contextRelative = false交换到我自己创建的DefaultRedirectStrategy实例,并使用contextRelative = true。
有没有一种更简单的方法可以告诉spring我想要在没有上下文路径的情况下全局重定向所有URL?我已经尝试在我的配置中注册DefaultRedirectStrategy,但这不起作用。
@Bean
public RedirectStrategy createRedirectStrategy()
{
// create the redirect strategy to set the urls to context relative
DefaultRedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
redirectStrategy.setContextRelative(true);
return redirectStrategy;
}
^这太简单了。不知道为什么春天不能让它发挥作用。
我找错了地方吗?
答案 0 :(得分:1)
我一直在努力解决同样的问题。尝试覆盖Spring Security的AuthenticationEntryPoint和SuccessHandler,以便他们使用没有Context Path的URL。当它让我感到震惊的时候,我的子域配置基本上就是说,每当有人打开http://app1.example.com/时,他/她应该被重定向到http://example.com/app1,所以就Tomcat如何看到网址以及Spring Security的情况而言确实存在。因此,也许不是在Spring Security中做疯狂的黑客攻击,以某种方式摆脱上下文路径本身会更好。
所以我最后做了什么,看起来如下。
我将两个子域重定向到同一个地址,这是我运行tomcat的地方。请注意,与之前的状态相反,我没有说明应用程序上下文。
http://app1.example.com/ -> http://localhost:8080
http://app2.example.com/ -> http://localhost:8080
现在要区分哪个子域应该触发我使用tomcat的虚拟主机的应用程序(阅读更多here)。
更新./tomcat/conf/server.xml看起来像这样
<Host name="app1.example.pl" appBase="app1"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="app1_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
<Host name="app2.example.pl" appBase="app2"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="apps2_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
现在我将两个应用程序的war文件分别放在app1和app2文件夹中(而不是webapps)(它们与webapp文件夹放在同一个父文件夹中)。最后要删除ContextPath,我们希望它们被部署为ROOT应用程序,因此对于两个应用程序来说战争应该命名为ROOT.war
我相信这比解决Spring Security更好的解决方案。同样,它允许您在SpringMVC中使用“redirect:”和亲戚路径。
答案 1 :(得分:0)
我发现使用DefaultRedirectStrategy是不够的,因为它丢失了协议信息(从HTTP重定向到HTTPS)。我仍然必须覆盖一堆spring对象来设置我自己的RedirectStrategy,但至少这可以用于删除上下文路径。
public class NoContextPathRedirectStrategy implements RedirectStrategy
{
private static final Logger logger = LoggerFactory.getLogger(NoContextPathRedirectStrategy.class);
@Override
public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) throws IOException
{
String redirectUrl = calculateRedirectUrl(request.getContextPath(), url);
redirectUrl = response.encodeRedirectURL(redirectUrl);
if (logger.isDebugEnabled())
{
logger.debug("Redirecting to '{}'", redirectUrl);
}
response.sendRedirect(redirectUrl);
}
private String calculateRedirectUrl(String contextPath, String url)
{
if (!UrlUtils.isAbsoluteUrl(url))
{
return url;
}
else
{
int contextPathIndex = url.indexOf(contextPath);
int contextPathLength = contextPath.length();
// check to see if there is a context path in this url
if (contextPathIndex >= 0)
{
// strip out the context path
url = url.substring(0, contextPathIndex) + url.substring(contextPathIndex + contextPathLength);
}
// check to see if there is a leading /
if (url.length() > 1 && url.charAt(0) == '/')
{
// remove the leading slash
url = url.substring(1);
}
return url;
}
}
}
答案 2 :(得分:0)
确实,您不能仅通过定义新的 DefaultRedirectStrategy
来更改 @Bean
那,我想这太全球化了
您可以改为使用 AbstractAuthenticationTargetUrlRequestHandler.redirectStrategy
的另一个实例通过其 DefaultRedirectStrategy
更改 public void setRedirectStrategy(RedirectStrategy redirectStrategy)
。
@Component
public class YourAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
YourAuthenticationSuccessHandler () {
// To avoid default behavior that prefixes `server.servlet.context-path`
DefaultRedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
redirectStrategy.setContextRelative(true); // <-- same as in the OP question
this.setRedirectStrategy(redirectStrategy); // <-- change redirect strategy
}
//
}