简体   繁体   中英

Spring Security 3.1

When I try to use a custom login form with Spring Security it keeps returning me to the /admin/login page regardless of whether I enter the correct credentials or not. When I use an empty <form-login /> the security check works fine. But has soon as I add a custom <form-login login-page="/admin/login" /> I keep getting returned to the same page. I have attempted adding a default-target-url="admin/forSale" /> but I am still returned to the login page. After providing the correct credentials and being returned to the login page I attempt to access a protected url and I am returned to the login page again, therefore I am 99% sure the security check was not performed at all.

The action="<c:url value='j_spring_security_check' />" in my jsp creates a url to http://localhost:8080/sharleepark/admin/j_spring_security_check . I assume the filter should still pick this up and processes the security accordingly?

I am convinced there is a simple mistake in my Controller or JSP that I am not picking up. I am using Tiles2 templating as well, could this be part of the problem? I have spent a couple of days on this and tried all the spring security tutorials I can find to no avail so many thanks in advance for your help.

spring-servlet.xml

<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.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  
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd ">

    <!-- Scans packages to auto declare the beans we require -->
    <context:component-scan base-package="au.com.sharleepark.controller" />
    <context:component-scan base-package="au.com.sharleepark.service" />
    <context:component-scan base-package="au.com.sharleepark.hibernate" />
    <context:component-scan base-package="au.com.sharleepark.helper" />

    <mvc:annotation-driven /> 
    <tx:annotation-driven />

    <!-- Map our static resources to a friendly URL -->
    <mvc:resources location="/static/" mapping="/static/**" />

    <!-- Specify the view resolver that we wish to use -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView" />
    </bean>

    <!-- Tell the tiles configurator where our tiles configuration files are located -->
    <bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
        <property name="definitions">
            <list>
                    <value>/WEB-INF/tiles.xml</value>
            </list>
        </property>
    </bean>

    <!-- Our datasource -->
    <!-- Defines our connection to the database -->
    <bean id="dataSource"
    class="org.springframework.jdbc.datasource.SingleConnectionDataSource"
    destroy-method="destroy">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://blah blah" />
        <property name="username" value="" />
        <property name="password" value="" />
        <property name="suppressClose" value="true" />
        <property name="autoCommit" value="true" />
    </bean>

    <!-- Session Factory -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="au.com.sharleepark.domain" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.hbm2ddl.auto">validate</prop>
                <prop key="show_sql">true</prop>
            </props>
        </property>
    </bean>

    <!-- Data Access Objects -->
    <!-- <bean id="hibernateDAO" class="au.com.sharleepark.hibernate.HibernateDaoImpl">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean> -->

    <!-- Transaction management -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <!-- Spring exception translation post processor for the DAO layer -->
    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

</beans>

spring-security.xml

<beans:beans xmlns="http://www.springframework.org/schema/security"
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.1.xsd">

    <http pattern="/static/**" security="none" />

    <http use-expressions="true">
        <intercept-url pattern="/admin/login" access="permitAll" />
        <intercept-url pattern="/admin/**" access="isAuthenticated()" />
        <intercept-url pattern="/**" access="permitAll" />
        <form-login login-page="/admin/login" />
        <logout /> <!-- Not there is currently a logout link anyway -->
    </http>

    <authentication-manager>
        <authentication-provider>
            <user-service>
                <user name="rod" password="koala" authorities="supervisor, teller, user" />
            </user-service>
        </authentication-provider>
    </authentication-manager>
</beans:beans>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0" metadata-complete="true">

    <display-name>Sharlee Park</display-name>

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

    <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>

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

    <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

adminLoginController.java (Controller)

package au.com.sharleepark.controller.admin;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

/**
 * Controller class for the administration login
 * @author Steve 
 * @version 1.00
 * 
 * Change History
 * 08/11/12 - Created
 */
@Controller
@RequestMapping(value="admin")
public class AdminLoginController {

    private static final Logger logger = Logger.getLogger(AdminLoginController.class);

    @RequestMapping(value="/login")
    public ModelAndView doView(@RequestParam(value="error", required=false) boolean error) {
        logger.info("processing Login");

        ModelAndView mav = new ModelAndView();
        mav.setViewName("admin/login");

        if (error) {
            logger.error("Invalid Credentials");
            mav.addObject("error", "Invalid login credentials");
        }
        return mav;
    }
}

adminLogin.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<div id="login">
    <div id="loginContent">
        <div class="error">${error}</div>
        <form name='sharleeParkLoginForm' action="<c:url value='j_spring_security_check' />" method='POST'>
            <fieldset>
                <ul class="fieldUL">
                    <li>
                        <label class="inputLabel" for="j_username">Username</label>
                        <span> 
                            <input class="inputField" type="text" tabindex="1" id="j_username" name="j_username" size="25" maxlength="25">
                        </span>
                    </li>
                </ul>
                <ul class="fieldUL">
                    <li>
                        <label class="inputLabel" for="spPassword">Password</label>
                        <span> 
                            <input class="inputField" type="password" tabindex="2" id="j_password" name="j_password" size="25" maxlength="25">
                        </span>
                    </li>
                </ul>
                <ul class="fieldUL">
                    <li><input name="submit" type="submit" value="Login"></li>
                </ul>
            </fieldset>
        </form>
        </div>
</div>

tiles.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE tiles-definitions PUBLIC
   "-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
   "http://tiles.apache.org/dtds/tiles-config_2_0.dtd">

<tiles-definitions>
    <definition name="base.definition" template="/WEB-INF/jsp/layout.jsp">
        <put-attribute name="title" value="" />
        <put-attribute name="header" value="/WEB-INF/jsp/header.jsp" />
        <put-attribute name="body" value="" />
    </definition>

....

    <!-- ADMIN PAGES -->
    <definition name="admin/login" extends="base.definition">
        <put-attribute name="title" value="Administration Login" />
        <put-attribute name="body" value="/WEB-INF/jsp/admin/adminLogin.jsp" />
    </definition>
....

</tiles-definitions>

Try to use <http auto-config="true" use-expressions="true"> .

From documentation about http auto-config attribute:

Automatically registers a login form, BASIC authentication, anonymous authentication, logout services, remember-me and servlet-api-integration. If set to "true", all of these capabilities are added (although you can still customize the configuration of each by providing the respective element). If unspecified, defaults to "false".

I bet something is wrong with your security configuration.

Why are you using use-expressions="true" in your http declaration? I do not see you use Spring-EL expressions... try to remove it and see if something changes.

Generally we do not handle the /login mapping in the controller. Spring security handles the login authentication and directs to the success Url. You can specify the view name for the login page in the spring-config.xml like this..

<mvc:view-controller path="/login" view-name="login"/>

and you can handle the success url mapping in the controller class. In this case if you specify the default-target-url="admin/forSale" then write a method to handle the /forSale mapping.

I think becaue you are handling the '/login' mapping in the controller its being directed to the login page for both success and failure..

ModelAndView mav = new ModelAndView();
mav.setViewName("admin/login");

But instead if there is no error then the view should be different mav.setViewName("admin/forSale")

I have worked it out. What solved the problem was adding the login-processing-url="/admin/j_spring_security_check" attribute to the <form-login> tag. I haven't worked with Spring Security before and I guess I just assumed the filters would magically find j_spring_security_check and process accordingly. Maybe the filters do pick it up if the j_spring_security_check is from the root URI (ie /sharleepark/j_spring_security_check) of the application? I have never seen the need for login-processing-url to be specified in any of the tutorials I have been looking at. Thanks again everyone for their input.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM