简体   繁体   中英

Spring MVC Hibernate Spring Security Login

I am trying to use spring security through login.

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

    <form:form action="j_spring_security_check" method="POST" modelAttribute="loginForm">
        <table>
            <tr>
                <td colspan="2" align="center">Already have an account - Login</td>
            </tr>
            <tr>
                <td>Email</td>
                <td><form:input path="emailID" /> <form:errors path="emailID" class="error" /></td>
            </tr>
            <tr>
                <td>Password</td>
                <td><form:password path="password" /> <form:errors path="password" class="error" /></td>
            </tr>
            <tr>
                <td colspan="2" align="center"><input type="submit" value="Login" /></td>
            </tr>   
            <tr>
                <td colspan="2" align="center">
                    <a href="${pageontext.request.contextPath }/forgotpassword">Forgot Password</a>
                </td>
            </tr>                                   
        </table>                                        
    </form:form>
    <span class="error">${loginMessage}</span>

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.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security.xsd">

    <!-- enable use-expressions -->
    <http auto-config="true" use-expressions="true">
        <intercept-url pattern="/admin**" access="hasRole('ROLE_admin')" />

        <!-- access denied page -->
        <access-denied-handler error-page="/403" />
        <form-login 
            login-page="/login" 
            default-target-url="/index"
            authentication-failure-url="/login?error" 
            username-parameter="username"
            password-parameter="password" />
        <logout logout-success-url="/login?logout" />
        <!-- enable csrf protection -->
        <csrf />
    </http>

    <beans:bean id="userAuthenticationProviderImpl" class="com.pir.authentication.UserAuthenticationProviderImpl" />

    <authentication-manager>
        <authentication-provider user-service-ref="userAuthenticationProviderImpl" >
            <password-encoder hash="plaintext" />    
        </authentication-provider>
    </authentication-manager>

</beans:beans>

UserAuthenticationProviderImpl.java

@Component(value = "authenticationProvider")
public class UserAuthenticationProviderImpl implements
        UserAuthenticationProvider {

    UserFunctionsService userFunctionsService;

    @Autowired(required=true)
    @Qualifier(value="userFunctionsService")
    public void setUserFunctionsService(UserFunctionsService userFunctionsService)
    {
        this.userFunctionsService = userFunctionsService;
    }

    /* (non-Javadoc)
     * @see com.pir.authentication.UserAuthenticationProvider#authenticate(org.springframework.security.core.Authentication)
     */
    @Override
    public Authentication authenticate(Authentication authentication) {
        // TODO Auto-generated method stub

        Users users = (Users) this.userFunctionsService.getUserDetails(authentication.getPrincipal().toString());

        if(users == null)
            throw new UsernameNotFoundException(String.format("Invalid credentials", authentication.getPrincipal()));

        String suppliedPasswordHash = authentication.getCredentials().toString();

        if(users.getPassword().equals(suppliedPasswordHash)){
            throw new BadCredentialsException("Invalid credentials");
        }
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(users, null);

        return token;
    }

}

Users.java

@Entity
@Table(name = "users")
public class Users {

    @NotNull
    @Id
    @Column(name = "userID")
    private int userID;

    @NotNull
    @Size(min=3, max=50)
    @Pattern(regexp = ".+@.+\\.[a-z]+")
    @Column(name = "emailID")
    private String emailID;

    @NotNull
    @Size(min=3, max=50)
    @Column(name = "firstName")
    private String firstName;

    @NotNull
    @Size(min=3, max=50)
    @Column(name = "lastName")
    private String lastName;

    @NotNull
    @Size(min=3, max=50)
    @Column(name = "password")
    private String password;

    @NotNull
    @Column(name = "mobileNo")
    private String mobileNo;


    @Column(name = "imageURL")
    private String imageURL;

    @NotNull
    @DateTimeFormat(pattern="MM/dd/yyyy")
    @Column(name = "dateOfBirth")
    private String dateOfBirth;

    @NotNull
    @Column(name = "gender")
    private String gender;

    @NotNull
    @Column(name = "userType")
    private String userType;

    @Lob
    private MultipartFile image;

        //getters and setters
}

pir-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:tx="http://www.springframework.org/schema/tx"
    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.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd"
    xmlns:mvc="http://www.springframework.org/schema/mvc">

    <context:annotation-config />

    <context:component-scan base-package="com.pir" />
    <mvc:annotation-driven />
    <tx:annotation-driven transaction-manager="myTransactionManager" />

    <bean id="myTransactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <bean id="userFunctionsDAO" class="com.pir.dao.UserFunctionsDAOImpl" />
    <bean id="userFunctionsService" class="com.pir.service.UserFunctionsServiceImpl" />

    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="1048576" />
    </bean>

<bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation">
            <value>classpath:hibernate.cfg.xml</value>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${jdbc.dialect}</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
    </bean>

    <bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource"
    p:driverClassName="com.mysql.jdbc.Driver"
    p:url="jdbc:mysql://localhost:3306/pir"
    p:username="root"
    p:password="user" />

    <bean id="tilesViewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass">
            <value>
                org.springframework.web.servlet.view.tiles3.TilesView
            </value>
        </property> 
    </bean>
    <bean id="tilesConfigurer"
        class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/tiles.xml</value>
            </list>
        </property>
    </bean>

</beans>

When I try to login, I expect to either login successfully or fail, but it gives HTTP Status 404 - error. This is first time I am trying to implement spring security, so dont have much knowledge about it. Whats is wrong I am doing in this code?

Did you rememeber to set the spring security filter chain in web.xml?

<!--  Spring security filter -->
  <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>

This coult be the reason, but ther are a couple of mistakes in your provider implementation.

 if(users.getPassword().equals(suppliedPasswordHash)){
            throw new BadCredentialsException("Invalid credentials");
        }
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(users, null);

First of all, the condition in the if is incorrect, this should be just the opposite:

 if(!users.getPassword().equals(suppliedPasswordHash)){
            throw new BadCredentialsException("Invalid credentials");
        }

The next line, where you create the UsernamePasswordAuthenticationToken, must be different, once the user is authenticated you must create the token setting the GrantedAuthorities while calling the constructor. If the userType field in user is the Authority that matches ROLE_admin specified in spring-security, you must do much more a kind this way:

Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority(user.getUserType()));
UsernamePasswordAuthenticationToken token = 
      new UsernamePasswordAuthenticationToken(users, null, authorities);

If you don't do this way, your provider will return an Authorization object with no access rigths granted

I think the problem is that the login processing of your spring-secrity-form-login-filter does not match the post url of your form.

In your form-login -tag, you did not set the login-processing-url paramter, therefor it uses its default /login *.

But in your html-login-form you used /j_spring_security_check . So they both do not match.

So either you have to correct the parameter in your spring-configuration or in your html form. (Because of the note below, I recommend to change the html form post url to /login but also would make the paraemter in the configuration explicite)

*The default value changed form /j_spring_security_check to /login in Spring Security 4.0, therere there are a lot of "old" tutorials that do not work anymore.

@See: http://docs.spring.io/spring-security/site/migrate/current/3-to-4/html5/migrate-3-to-4-xml.html#m3to4-xmlnamespace-form-login

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