Java Spring Security-更改重定向策略的所有实例
我有一个运行多个WAR文件的tomcat实例。tomcat实例被代理在Apache服务器后面,以便剥离上下文路径。相反,我使用的是子域: 基本上,我的设置如下所示:Java Spring Security-更改重定向策略的所有实例,java,spring,apache,tomcat,spring-security,Java,Spring,Apache,Tomcat,Spring Security,我有一个运行多个WAR文件的tomcat实例。tomcat实例被代理在Apache服务器后面,以便剥离上下文路径。相反,我使用的是子域: 基本上,我的设置如下所示: http://localhost:8080/app1 -> http://app1.example.com/ http://localhost:8080/app2 -> http://app2.example.com/ 我需要做的是使所有重定向与上下文相关,因为我不再在URL中包含上下文路径。我注意到Spring安全性
http://localhost:8080/app1 -> http://app1.example.com/
http://localhost:8080/app2 -> http://app2.example.com/
我需要做的是使所有重定向与上下文相关,因为我不再在URL中包含上下文路径。我注意到Spring安全性允许使用默认的类DefaultRedirectStrategy将重定向设置为“上下文相关”。为了使重定向正常工作,我必须覆盖多个对象,这样我就可以简单地将contextRelative=false的DefaultRedirectStrategy的默认实例替换为自己创建的contextRelative=true的DefaultRedirectStrategy实例
有没有一种更简单的方法可以告诉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;
}
^这太容易了。不知道为什么spring不允许这样做
我找错地方了吗?我发现使用DefaultRedirectStrategy是不够的,因为它会丢失协议信息(从HTTP重定向到HTTPS)。我仍然需要覆盖一堆spring对象来设置我自己的重定向策略,但至少这可以用于删除上下文路径
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;
}
}
}
我和你一直在同一个问题上挣扎。试图覆盖Spring Security的AuthenticationEntryPoint和SuccessHandler,以便它们使用不带上下文路径的URL。当我意识到这一点时,我对子域的配置基本上是说,每当有人打开他/她时,他/她都应该被重定向到这样一个位置:Tomcat如何看待url,因此Spring Security确实存在上下文。因此,与其在SpringSecurity中进行疯狂的黑客攻击,不如以某种方式摆脱上下文路径本身 因此,我在最后所做的,如下所示 子域配置 我将两个子域重定向到同一个地址,这就是我运行tomcat的地方。请注意,与前面的状态相反,我并没有说任何关于应用程序上下文的内容
http://app1.example.com/ -> http://localhost:8080
http://app2.example.com/ -> http://localhost:8080
虚拟主机配置
现在,为了区分哪个子域应该触发哪个应用程序,我使用tomcat的虚拟主机(阅读更多)
更新的./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中(它们与webapp文件夹放在同一个父文件夹中),而不是放在webapp中。最后,要删除ContextPath,我们希望将它们部署为根应用程序,因此两个应用程序的war应命名为ROOT.war
结论
我相信这是比破解Spring安全性更好的解决方案。它还允许您在SpringMVC中使用“重定向:”以及相关路径。事实上,您不能仅仅通过定义一个新的
@Bean
来更改DefaultRedirectStrategy
我想这太全球化了
您可以改为使用另一个DefaultRedirectStrategy
实例,通过其public void setRedirectStrategy(redirectStrategy redirectStrategy)
更改AbstractAuthenticationTargetUrlRequestHandler.redirectStrategy
@组件
公共类YourAuthenticationSuccessHandler扩展了SavedRequestStataWareAuthenticationSuccessHandler{
YourAuthenticationSuccessHandler(){
//避免前缀为'server.servlet.context-path'的默认行为`
DefaultRedirectStrategy redirectStrategy=新的DefaultRedirectStrategy();
redirectStrategy.setContextRelative(true)//
@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
}
//
}