java - Spring post 重定向到 access-denied while get 工作

标签 java xml spring spring-mvc post

我对有点重复的帖子表示歉意,我昨天问了一个关于这个问题的问题,但是我没有很好地陈述问题,因此反馈没有用。从那以后,我对这个问题有了更多的了解,并且可以用更清晰、简洁的方式表达出来,希望有助于解决这个问题。

每当我尝试发布到页面时, Controller 都会将 url 映射到 mvc-dispatch-servlet.xml 指定的访问拒绝处理程序。如果我尝试访问某个页面,那么它会命中正确的@requestmapping,并且一切正常。

Get and post to the same url getting different results 我尝试过添加

<intercept-url pattern="/pages/ReceiveFile" access="permitAll"/>

什么也不做。

我最近刚刚将这个问题缩小到

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

这似乎阻碍了后期操作。如果我将其更改为/pages/*,那么我可以发布到/ReceiveFile 页面,因为它在 web.xml 中以这种方式映射。这完全跳过了主 Controller 。使用该设置,如果我尝试转到pages/ReceiveFile,它仍然会通过 Controller 并转到 403 页面。我不认为通过所有后期操作绕过我的 Controller 是一个好的永久解决方案。

如何允许这些后期操作进行?

谢谢!

主 Controller .java 删除一些代码以减少不必要的长度

@Controller
public class MainController {
  String URLroot = "pages/";

  @PreAuthorize("hasRole('_discover')")
  @RequestMapping(value = {"/discover/**" }, method = RequestMethod.GET)
  public ModelAndView discover(HttpServletRequest request) {
    StringBuffer mapping = request.getRequestURL();
    String URLoffset = getURLoffset(mapping);

    ModelAndView model = new ModelAndView();
    model.addObject("title", "Spring Security Login Form - Database Authentication");
    model.addObject("message", "This is default page no longer!");
    model.setViewName(URLoffset);
    return model;

  }

  /**
   * Upload single file using Spring Controller
   */
  @RequestMapping(value = "/ReceiveFile", method = {RequestMethod.POST,RequestMethod.GET})
  public ModelAndView test(){

    //Do useful things which require post.....


    ModelAndView model = new ModelAndView();
    model.setViewName("springtest");
    return model;
  }


  @RequestMapping(value = "/admin**", method = RequestMethod.GET)
  public ModelAndView adminPage(HttpServletRequest request) {
    StringBuffer mapping = request.getRequestURL();
    String URLoffset = getURLoffset(mapping);

    ModelAndView model = new ModelAndView();
    model.addObject("title", "Spring Security Login Form - Database Authentication");
    model.addObject("message", "This page is for ROLE_ADMIN only!");
    model.setViewName(URLoffset);

    return model;

  }

  @RequestMapping(value = "/signout", method = { RequestMethod.POST, RequestMethod.GET })
  public ModelAndView login() {

    ModelAndView model = new ModelAndView();
    model.setViewName("signout");
    return model;

  }

  @RequestMapping(value = "/login", method = RequestMethod.GET)
  public ModelAndView login(@RequestParam(value = "error", required = false) String error,
                            @RequestParam(value = "logout", required = false) String logout) {

    ModelAndView model = new ModelAndView();
    if (error != null) {
      model.addObject("error", "Invalid username and password!");
    }

    if (logout != null) {
      model.addObject("msg", "You've been logged out successfully.");
    }
    model.setViewName("login");
    return model;

  }

  //for 403 access denied page
  @RequestMapping(value = "/403", method = { RequestMethod.POST, RequestMethod.GET })
  public ModelAndView accesssDenied() {

    ModelAndView model = new ModelAndView();

    //check if user is logged in
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    if (!(auth instanceof AnonymousAuthenticationToken)) {
//      UserDetails userDetail = (UserDetails) auth.getPrincipal();
      System.out.println(auth.getName());
      model.addObject("username", auth.getName());

    }

    model.setViewName("/403");
    return model;

  }

  /**
   * Upload single file using Spring Controller
   */
  @RequestMapping(value = "/uploadFile2", method = {RequestMethod.POST,RequestMethod.GET})
  public @ResponseBody
  String uploadFileHandler(@RequestParam("name") String name,
          @RequestParam("file") MultipartFile file) {

      if (!file.isEmpty()) {
          try {
              byte[] bytes = file.getBytes();

              // Creating the directory to store file
              String rootPath = System.getProperty("catalina.home");
              File dir = new File(rootPath + File.separator + "tmpFiles");
              if (!dir.exists())
                  dir.mkdirs();

              // Create the file on server
              File serverFile = new File(dir.getAbsolutePath()
                      + File.separator + name);
              BufferedOutputStream stream = new BufferedOutputStream(
                      new FileOutputStream(serverFile));
              stream.write(bytes);
              stream.close();

              instance.debug("FileUploadController" + " uploadFileHandler", "Server File Location=" + serverFile.getAbsolutePath());


              return "You successfully uploaded file=" + name;
          } catch (Exception e) {
              return "You failed to upload " + name + " => " + e.getMessage();
          }
      } else {
          return "You failed to upload " + name
                  + " because the file was empty.";
      }
  }


}

mvc-dispatch-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <context:component-scan base-package="com.mkyong.*" />
    <!-- Currently not working. Made a work around by having resources at /resources and pages at /pages -->
  <mvc:resources location="/resources/" mapping="/resources/" />

    <!-- also add the following beans to get rid of some exceptions -->
    <bean
        class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
    <bean
        class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    </bean>

    <bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- setting maximum upload size -->
        <property name="maxUploadSize"> 
            <value>100000</value>
        </property>        
    </bean>

    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/pages/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>

</beans>

spring-security.xml

<beans:beans xmlns="http://www.springframework.org/schema/security"
  xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:beans="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.2.xsd
    http://www.springframework.org/schema/context 
  http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:component-scan base-package="com.mkyong.*" />
    <!-- enable use-expressions -->
    <http auto-config="true" use-expressions="true">
        <!-- login page must be available to all. The order matters, if this is after something which secures the page this will fail. -->
<!--        <intercept-url pattern="/SignupUserServlet" access="permitAll"/> -->
        <intercept-url pattern="/pages/ReceiveFile" access="permitAll"/> 
        <intercept-url pattern="/pages/fileUpdate2" access="permitAll"/>
        <intercept-url pattern="/pages/login" access="permitAll" />
        <intercept-url pattern="/pages/admin/**" access="hasRole('_admin')" />
        <intercept-url pattern="/pages/trade/**" access="hasRole('_trader')" />
        <intercept-url pattern="/pages/discover/**" access="hasRole('_users')" />       
        <!-- access denied page -->
        <access-denied-handler error-page="/pages/403" />
        <form-login 
            login-page="/pages/login" 
            default-target-url="/pages/common/redirectportal" 
            authentication-failure-url="/pages/login?error" 
            username-parameter="username"
            password-parameter="password" />
        <logout logout-url="/pages/logout" logout-success-url="/pages/login?logout" />
        <!-- enable csrf protection -->
        <csrf/>
    </http>

    <!-- Select users and user_roles from database -->
    <authentication-manager>
        <authentication-provider ref="customAuthenticationProvider"/>
        <!--<jdbc-user-service data-source-ref="dataSource"
                users-by-username-query=
                    "select email,pwhash, enabled from users where email=?"
                authorities-by-username-query=
                    "select email, groupname from usergroups where email =?  " /> 
        </authentication-provider> -->
    </authentication-manager>

</beans:beans>

web.xml

<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">


        <!-- Spring MVC -->
    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

      <servlet>
    <servlet-name>InitServlet</servlet-name>
    <servlet-class>servlet.InitServlet</servlet-class>
    <init-param>
      <param-name>configfile</param-name>
    </init-param>
    <load-on-startup>2</load-on-startup>
  </servlet>

  <servlet>
    <servlet-name>AdminServlet</servlet-name>
    <servlet-class>servlet.admin.AdminServlet</servlet-class>
    <load-on-startup>3</load-on-startup>
  </servlet>

  <servlet>
    <servlet-name>UserServlet</servlet-name>
    <servlet-class>servlet.user.UserServlet</servlet-class>
    <load-on-startup>4</load-on-startup>
  </servlet>

  <servlet>
    <servlet-name>SignupUserServlet</servlet-name>
    <servlet-class>servlet.user.SignupUserServlet</servlet-class>
    <load-on-startup>5</load-on-startup>
  </servlet>

  <servlet>
   <servlet-name>ReceiveFile</servlet-name>
    <servlet-class>servlet.user.ReceiveFile</servlet-class>
    <load-on-startup>6</load-on-startup>
  </servlet>

  <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/pages/*</url-pattern>
    </servlet-mapping>

  <servlet-mapping>
   <servlet-name>AdminServlet</servlet-name>
   <url-pattern>/AdminServlet</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
   <servlet-name>UserServlet</servlet-name>
   <url-pattern>/UserServlet</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
   <servlet-name>SignupUserServlet</servlet-name>
   <url-pattern>/SignupUserServlet</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
   <servlet-name>ReceiveFile</servlet-name>
   <url-pattern>/ReceiveFile</url-pattern>
  </servlet-mapping>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring-security.xml,
            /WEB-INF/spring-database.xml
        </param-value>
    </context-param>

    <!-- Spring Security -->
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

最佳答案

我不是 100% 确定,但我认为正是这行配置导致了 spring-security.xml 中的问题:

<csrf/>

如果启用CSRF在安全性中,您的帖子请求需要更新以包含一些额外的信息。它解释了为什么 GET 有效,但 POST 无效。

对于您的情况,请尝试将其删除,然后查看是否可以解决问题。

关于java - Spring post 重定向到 access-denied while get 工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25210174/

相关文章:

java - 将 java 对象可靠地存储在文件中的最少代码

java - 使用 XStream 中的属性反序列化 XML 文本元素

java - 更新 Spring Boot 实体管理器 jpa 的主键

java - 搜索二维数组中是否存在一行,其总和等于同一二维数组中其他两行的总和

java - HTML实体解码java

java - 无法读取 log4j 属性文件

java - 用于接触 netbeans 的不同软件包

javascript - 我如何用 jquery 解析那个 xml 文件

spring - 我应该将Maven项目的应用程序配置文件放在哪里?

java - 两个对象的 Spring 表单验证