Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring Security-更改重定向策略的所有实例_Java_Spring_Apache_Tomcat_Spring Security - Fatal编程技术网

Java Spring Security-更改重定向策略的所有实例

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安全性

我有一个运行多个WAR文件的tomcat实例。tomcat实例被代理在Apache服务器后面,以便剥离上下文路径。相反,我使用的是子域:

基本上,我的设置如下所示:

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 &quot;%r&quot; %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 &quot;%r&quot; %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
  }

  //
}