【问题标题】:Redirect to an external URL from controller action in Spring MVC从 Spring MVC 中的控制器操作重定向到外部 URL
【发布时间】:2013-07-31 02:47:51
【问题描述】:

我注意到以下代码将用户重定向到项目内的 URL,

@RequestMapping(method = RequestMethod.POST)
public String processForm(HttpServletRequest request, LoginForm loginForm, 
                          BindingResult result, ModelMap model) 
{
    String redirectUrl = "yahoo.com";
    return "redirect:" + redirectUrl;
}

然而,以下内容按预期正确重定向,但需要 http:// 或 https://

@RequestMapping(method = RequestMethod.POST)
    public String processForm(HttpServletRequest request, LoginForm loginForm, 
                              BindingResult result, ModelMap model) 
    {
        String redirectUrl = "http://www.yahoo.com";
        return "redirect:" + redirectUrl;
    }

我希望重定向始终重定向到指定的 URL,无论它是否具有有效协议并且不想重定向到视图。我该怎么做?

谢谢,

【问题讨论】:

    标签: java spring jsp spring-mvc


    【解决方案1】:

    您可以通过两种方式来做到这一点。

    第一:

    @RequestMapping(value = "/redirect", method = RequestMethod.GET)
    public void method(HttpServletResponse httpServletResponse) {
        httpServletResponse.setHeader("Location", projectUrl);
        httpServletResponse.setStatus(302);
    }
    

    第二:

    @RequestMapping(value = "/redirect", method = RequestMethod.GET)
    public ModelAndView method() {
        return new ModelAndView("redirect:" + projectUrl);
    }
    

    【讨论】:

    • 直接返回String而不是ModelAndView会更简单。
    • 似乎在第一种方法中您应该将返回代码设置为 302。否则服务器将返回带有代码 200 和 Location 标头的响应,这在我的情况下不会导致重定向(Firefox 41.0)。
    • 我们可以在重定向到外部 URL 的过程中添加 cookie。
    • 第一种方法需要@ResponseStatus(HttpStatus.FOUND)
    • @Rinat Mukhamedgaliev 在这个 ModelAndView("redirect:" + projectUrl);声明如果添加的东西是值,那么默认的键是什么?
    【解决方案2】:

    您可以使用RedirectView。复制自JavaDoc

    重定向到绝对、上下文相对或当前请求相对 URL 的视图

    例子:

    @RequestMapping("/to-be-redirected")
    public RedirectView localRedirect() {
        RedirectView redirectView = new RedirectView();
        redirectView.setUrl("http://www.yahoo.com");
        return redirectView;
    }
    

    您也可以使用ResponseEntity,例如

    @RequestMapping("/to-be-redirected")
    public ResponseEntity<Object> redirectToExternalUrl() throws URISyntaxException {
        URI yahoo = new URI("http://www.yahoo.com");
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setLocation(yahoo);
        return new ResponseEntity<>(httpHeaders, HttpStatus.SEE_OTHER);
    }
    

    当然,如其他人所说,返回redirect:http://www.yahoo.com

    【讨论】:

    • RedirectView 是唯一对我有用的!
    • 我在使用重定向视图时有一种奇怪的行为,在 webshpere 上我得到:[code][27/04/17 13:45:55:385 CDT] 00001303 webapp E com.ibm.ws .webcontainer.webapp.WebApp logServletError SRVE0293E: [Error de servlet]-[DispatcherPrincipal]: java.io.IOException: 模式不允许在 mx.isban.security.components.SecOutputFilter$WrapperRsSecured.sendRedirect(SecOutputFilter.java:234) 在javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:145)[代码]
    【解决方案3】:

    查看 UrlBasedViewResolverRedirectView 的实际实现,如果您的重定向目标以 / 开头,则重定向将始终是 contextRelative。因此,发送 //yahoo.com/path/to/resource 也无助于获得协议相对重定向。

    因此,要实现您正在尝试的目标,您可以执行以下操作:

    @RequestMapping(method = RequestMethod.POST)
    public String processForm(HttpServletRequest request, LoginForm loginForm, 
                              BindingResult result, ModelMap model) 
    {
        String redirectUrl = request.getScheme() + "://www.yahoo.com";
        return "redirect:" + redirectUrl;
    }
    

    【讨论】:

    • 但是这样重定向是 GET 还是仍然是 POST?如何重定向为 POST?
    • 实际上默认情况下这会返回一个 302,这意味着它应该针对提供的 url 发出一个 GET。对于保持相同方法的重定向,您还应该设置不同的代码(从 HTTP/1.1 开始为 307)。但是我很确定如果由于安全问题而使用不同的主机/端口组合的绝对地址,浏览器会阻止它。
    【解决方案4】:

    您可以使用ResponseEntity 以非常简洁的方式执行此操作,如下所示:

      @GetMapping
      ResponseEntity<Void> redirect() {
        return ResponseEntity.status(HttpStatus.FOUND)
            .location(URI.create("http://www.yahoo.com"))
            .build();
      }
    

    【讨论】:

    • 这应该是公认的答案。非常容易设置和使用。
    • 这个答案是完美的,因为它允许重定向,而且您可以选择不重定向,只返回正文中的内容。非常灵活。
    【解决方案5】:

    另一种方法是使用sendRedirect 方法:

    @RequestMapping(
        value = "/",
        method = RequestMethod.GET)
    public void redirectToTwitter(HttpServletResponse httpServletResponse) throws IOException {
        httpServletResponse.sendRedirect("https://twitter.com");
    }
    

    【讨论】:

      【解决方案6】:

      对我来说工作正常:

      @RequestMapping (value = "/{id}", method = RequestMethod.GET)
      public ResponseEntity<Object> redirectToExternalUrl() throws URISyntaxException {
          URI uri = new URI("http://www.google.com");
          HttpHeaders httpHeaders = new HttpHeaders();
          httpHeaders.setLocation(uri);
          return new ResponseEntity<>(httpHeaders, HttpStatus.SEE_OTHER);
      }
      

      【讨论】:

      • 我认为这种方法比 RedirectView 更好,因为它也适用于邮递员。
      【解决方案7】:

      对于外部网址,您必须使用“http://www.yahoo.com”作为重定向网址。

      这在 Spring 参考文档的redirect: prefix 中有说明。

      重定向:/myapp/some/resource

      将相对于当前 Servlet 上下文进行重定向,而诸如

      之类的名称

      重定向:http://myhost.com/some/arbitrary/path

      将重定向到绝对 URL

      【讨论】:

      • 这是 imo 最准确的答案。该操作要求将 URL 重定向为绝对 URL,即使其中没​​有方案。答案是:不,你不能,你必须指定方案。我看到的所有其他答案都有效,因为他们使用http://www.yahoo.comhttp://www.google.com 等作为他们解决方案的示例输入。如果他们使用www.yahoo.com,无论ResponseEntity 还是redirect:,都会崩溃。尝试使用 Spring boot 2.5.2 和 Chrome、Firefox 和 Safari。
      【解决方案8】:

      您是否尝试过RedirectView 可以提供 contextRelative 参数?

      【讨论】:

      • 该参数对于以/ 开头(或不以/ 开头)的路径很有用,以检查它是否应该与webapp 上下文相关。重定向请求仍将针对同一主机。
      【解决方案9】:

      这对我有用,并解决了“对预检请求的响应未通过访问控制检查...”问题。

      控制器

          RedirectView doRedirect(HttpServletRequest request){
      
              String orgUrl = request.getRequestURL()
              String redirectUrl = orgUrl.replaceAll(".*/test/","http://xxxx.com/test/")
      
              RedirectView redirectView = new RedirectView()
              redirectView.setUrl(redirectUrl)
              redirectView.setStatusCode(HttpStatus.TEMPORARY_REDIRECT)
              return redirectView
          }
      
      

      并启用安全性

      @EnableWebSecurity
      class SecurityConfigurer extends WebSecurityConfigurerAdapter{
          @Override
          protected void configure(HttpSecurity http) throws Exception {
              http.cors().and().csrf().disable()
          }
      }
      

      【讨论】:

        【解决方案10】:

        简而言之,"redirect://yahoo.com" 会将您借给yahoo.com

        "redirect:yahoo.com" 将借给你your-context/yahoo.com 即前-localhost:8080/yahoo.com

        【讨论】:

        • 两种解决方案都有相同的命令:“简而言之“redirect:yahoo.com”与“其中”作为“redirect:yahoo.com”,并且只有相对 url 重定向有效。
        猜你喜欢
        • 1970-01-01
        • 2019-01-14
        • 1970-01-01
        • 2010-12-05
        • 2013-08-06
        • 2016-02-06
        • 2012-04-02
        • 2023-03-22
        • 1970-01-01
        相关资源
        最近更新 更多