自定义登录+ Spring Security + Tiles + Request方法' POST'不支持

时间:2015-02-14 14:25:22

标签: spring spring-mvc spring-security apache-tiles

我正在尝试使用Spring(v.4.1.0)安全性(v.3.2.5)保护访问URL (例如/ user / subscriptions),并在提交后收到以下错误用户名/密码和csrf令牌:

  

HTTP ERROR 405访问/ j_spring_security_check时出现问题。原因:         请求方法' POST'不支持

我有以下配置。 的web.xml

<!--Hook into 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>/rest_services/*</url-pattern>
  <url-pattern>/users/*</url-pattern>
</filter-mapping>   

Spring安全上下文:

<security:http  auto-config="false" authentication-manager-ref="jdbcAuthenticationManager">
    <security:intercept-url pattern="/users/**/*" access="ROLE_USER"/>
    <security:intercept-url pattern="/login/custom_login" access="ROLE_ANONYMOUS"/>
    <security:form-login
        login-page="/login/custom_login"
        username-parameter="username"
        password-parameter="password" />
    <security:logout logout-success-url="/custom_login?logout" />
    <!-- enable csrf protection -->
    <csrf/>
</security:http>

CustomLoginController:

@Controller
@RequestMapping("/login")
public class CustomLoginController {

    protected static Logger LOG = Logger.getLogger(CustomLoginController.class);

    //Spring Security see this :
    @RequestMapping(value = "custom_login", method = RequestMethod.GET)
    public String 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.");
        }

        return "login_def";
    }
}

瓷砖定义

<definition name="login_def" extends="defaultTemplate_m">
    <put-attribute name="title" value="Podcastpedia"/>
    <put-attribute name="page_description" value="Podcastpedia.org, knowledge to go"/>
    <put-attribute name="body-id" value="latest-episodes-podcast-subscriptions" />   
    <put-attribute name="content" value="/WEB-INF/jsp/user/login.jsp"/>                 
</definition>   

的login.jsp

<form name='loginForm'
    action="<c:url value='/j_spring_security_check' />" method='POST'>

    <table>
    <tr>
        <td>User:</td>
        <td><input type='text' name='username' value=''></td>
    </tr>
    <tr>
        <td>Password:</td>
        <td><input type='password' name='password' /></td>
    </tr>
    <tr>
            <td colspan='2'>
                           <input name="submit" type="submit" value="submit" />
                           </td>
    </tr>
   </table>

   <input type="hidden" 
                name="${_csrf.parameterName}" value="${_csrf.token}" /> 
</form>

Tiles-context配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:p="http://www.springframework.org/schema/p" 
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">


    <!-- Views mapped in views.properties (PDF, XLS classes, and others) --> 
    <bean id="contentNegotiatingResolver"
              class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="order"
                  value="#{T(org.springframework.core.Ordered).HIGHEST_PRECEDENCE}" />
         <property name="favorPathExtension" value="true"/>
        <property name="contentNegotiationManager">
            <bean class="org.springframework.web.accept.ContentNegotiationManager">
                <constructor-arg>
                    <bean class="org.springframework.web.accept.PathExtensionContentNegotiationStrategy">
                        <constructor-arg>
                            <map>
                              <entry key="html" value="text/html"/>
                              <entry key="pdf" value="application/pdf"/>
                              <entry key="xsl" value="application/vnd.ms-excel"/>
                              <entry key="xml" value="application/xml"/>
                              <entry key="json" value="application/json"/>
                              <entry key="atom" value="application/xml"/>
                            </map>
                        </constructor-arg>
                    </bean>
                </constructor-arg>
            </bean>
        </property>         
     </bean>

   <bean id="tilesViewResolver"
     class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.tiles3.TilesView" />
        <property name="order" value="#{contentNegotiatingResolver.order+1}" />
    </bean>


    <bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
      <property name="basename" value="views"/>
      <property name="order" value="#{tilesViewResolver.order+1}" />
    </bean>

    <bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer"> 
        <property name="definitions">       
            <list>
                <value>/WEB-INF/tile-defs/templates.xml</value>
                <value>/WEB-INF/tile-defs/definitions.xml</value>
            </list>     
        </property> 
    </bean>

</beans>

没有Tiles的项目中的相同配置没有任何问题。你可以告诉我我可能做错了什么......尝试可以在https://github.com/podcastpedia/podcastpedia-web/tree/spring-security-custom-login

找到

问题与HTTP Status 405 - Request method 'POST' not supported occurs when try to submit spring security's custom login form的问题非常相似,但还没有答案......

1 个答案:

答案 0 :(得分:1)

CustomLoginController中,您已login注释了@RequestMapping(value = "custom_login", method = RequestMethod.GET)方法。只有当HTTP请求方法是GET而不是POST时,才会调用此方法。

也许你的意思是@RequestMapping(value = "custom_login", method = RequestMethod.POST)