spring security 4.1 中自定義登錄界面和擴展login controller

spring security 4.1.3 中自定義登錄界面 並且擴展 login controller的實現和配置方法

參考文檔 : 自定義Login/Logout Filter、AuthenticationProvider、AuthenticationToken
Spring Security Reference
1. 需求:
在項目中需要用spring security來進行權限管理。並且需要對login的功能進行擴展。比如:登錄成功以後,把用戶名放入session中
2. 配置
web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee   
        http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="Whale" version="3.1">
    <display-name>Whale</display-name>
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <async-supported>true</async-supported>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:META-INF/applicationContext.xml,
            classpath:META-INF/applicationContext-security.xml
        </param-value>
    </context-param>
    <!-- 防止內存泄漏 -->
    <listener>
        <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:META-INF/spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>
    <servlet-mapping>
        <servlet-name>SpringMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <!-- 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>
    <!-- end -->
    <welcome-file-list>
        <welcome-file>/views/welcome.jsp</welcome-file>
    </welcome-file-list>
    <servlet-mapping>
        <servlet-name>jsp</servlet-name>
        <url-pattern>*.jsp</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>10</session-timeout>
    </session-config>
</web-app>

applicationContext-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-4.3.xsd
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.1.xsd">
    <http auto-config="false">
        <intercept-url pattern="/" access="permitAll" />
        <intercept-url pattern="/admin**" access="hasRole('ADMIN')" />
        <intercept-url pattern="/dba**" access="hasRole('DBA')" />
        <!-- 自定義登錄的界面 -->
        <form-login login-page="/views/login.jsp" username-parameter="username" password-parameter="password" authentication-failure-url="/views/accessDenied.jsp" />
        <!-- 自定登錄的filter -->
        <custom-filter before="FORM_LOGIN_FILTER" ref="customLoginFilter" />
        <!-- 自定退出的filter -->
        <custom-filter before="LOGOUT_FILTER" ref="customLogoutFilter" />
    </http>
    <authentication-manager alias="authenticationManager">
        <authentication-provider>
            <user-service>
                <user name="user" password="user" authorities="ROLE_USER" />
                <user name="admin" password="root123" authorities="ROLE_ADMIN" />
                <user name="dba" password="dba" authorities="ROLE_ADMIN,ROLE_DBA" />
            </user-service>
        </authentication-provider>
    </authentication-manager>
    <!-- 指定登錄filter的實現類 -->
    <beans:bean id="customLoginFilter" class="com.ninelephas.whale.springsecurity.CustomLoginFilter">
        <beans:property name="authenticationManager" ref="authenticationManager" />
    </beans:bean>
    <!-- 指定退出filter的實現類 -->
    <beans:bean id="customLogoutFilter" class="com.ninelephas.whale.springsecurity.CustomLogoutFilter">
        <!-- 處理退出的虛擬url -->
        <beans:property name="filterProcessesUrl" value="/logout" />
        <!-- 退出處理成功後的默認顯示url -->
        <beans:constructor-arg index="0" value="/" />
        <beans:constructor-arg index="1">
            <!-- 退出成功後的handler列表 -->
            <beans:array>
                <beans:bean id="securityContextLogoutHandler" class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
                <!-- 加入了開發人員自定義的退出成功處理 -->
                <beans:bean id="customLogoutSuccessHandler" class="com.ninelephas.whale.springsecurity.CustomLogoutHandler" />
            </beans:array>
        </beans:constructor-arg>
    </beans:bean>
</beans:beans>
  1. 這裏要注意幾點:
    a. http auto-config=”false” 不能設置成auto-config=”true”
    b. 自定義登錄的界面

    <form-login login-page="/views/login.jsp" username-parameter="username" password-parameter="password" authentication-failure-url="/views/accessDenied.jsp" />

    c. 自定義登錄的filter

    <custom-filter before="FORM_LOGIN_FILTER" ref="customLoginFilter" />

    d. 定義 authentication-manager 的別名,指定給filter來使用

    <authentication-manager alias="authenticationManager">

    e. 指定登錄filter的實現類

    <beans:bean id="customLoginFilter" class="com.ninelephas.whale.springsecurity.CustomLoginFilter">
    <beans:property name="authenticationManager" ref="authenticationManager" />
    </beans:bean>
  2. customLoginFilter 的代碼如下:
/**
 * @Title: CustomLoginFilter.java
 * @Package com.ninelephas.whale.springsecurity
 * @Description: TODO
 *               Copyright: Copyright (c) 2016
 *               Company:九象網絡科技(上海)有限公司
 * 
 * @author roamerxv
 * @date 2016年9月6日 上午11:23:31
 * @version V1.0.0
 */

package com.ninelephas.whale.springsecurity;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @ClassName: CustomLoginFilter
 * @Description: TODO
 * @author Comsys-roamerxv
 * @date 2016年9月6日 上午11:23:31
 *
 */

public class CustomLoginFilter extends UsernamePasswordAuthenticationFilter {
    /**
     * Logger for this class
     */
    private static final Logger logger = LogManager.getLogger(CustomLoginFilter.class.getName());

    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        logger.debug("attemptAuthentication(HttpServletRequest, HttpServletResponse) - start"); //$NON-NLS-1$

        String username = obtainUsername(request).toUpperCase().trim();
        String password = obtainPassword(request);
        Authentication returnAuthentication = null;
        try {
            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
            returnAuthentication = this.getAuthenticationManager().authenticate(authRequest);
        } catch (Exception e) {
            logger.error(e);
            throw e ;
        }

        logger.debug("attemptAuthentication(HttpServletRequest, HttpServletResponse) - end"); //$NON-NLS-1$
        return returnAuthentication;
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request,
        HttpServletResponse response,
        FilterChain chain,
        Authentication authResult) throws IOException, ServletException {
        logger.debug("successfulAuthentication(HttpServletRequest, HttpServletResponse, FilterChain, Authentication) - start"); //$NON-NLS-1$
        super.successfulAuthentication(request, response, chain, authResult);
        logger.debug("登錄成功!");
        logger.debug("successfulAuthentication(HttpServletRequest, HttpServletResponse, FilterChain, Authentication) - end"); //$NON-NLS-1$
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request,
        HttpServletResponse response, AuthenticationException failed)
        throws IOException, ServletException {
        logger.debug("unsuccessfulAuthentication(HttpServletRequest, HttpServletResponse, AuthenticationException) - start"); //$NON-NLS-1$
        super.unsuccessfulAuthentication(request, response, failed);
        logger.debug("登錄失敗!");
        logger.debug("unsuccessfulAuthentication(HttpServletRequest, HttpServletResponse, AuthenticationException) - end"); //$NON-NLS-1$
    }
}

CustomLogoutFilter.java

/**
 * @Title: CustomLogoutFilter.java
 * @Package com.ninelephas.whale.springsecurity
 * @Description: TODO
 *               Copyright: Copyright (c) 2016
 *               Company:九象網絡科技(上海)有限公司
 * 
 * @author roamerxv
 * @date 2016年9月6日 下午3:13:07
 * @version V1.0.0
 */

package com.ninelephas.whale.springsecurity;

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

/**
 * @ClassName: CustomLogoutFilter
 * @Description: TODO
 * @author Comsys-roamerxv
 * @date 2016年9月6日 下午3:13:07
 *
 */

public class CustomLogoutFilter extends LogoutFilter {
    /**
     * Logger for this class
     */
    private static final Logger logger = LogManager.getLogger(CustomLogoutFilter.class.getName());

    /**
     * 
     * 創建一個新的實例 CustomLogoutFilter.
     * <p>
     * Title:
     * </p>
     * <p>
     * Description:
     * </p>
     * 
     * @param logoutSuccessHandler
     * @param handlers
     */

    public CustomLogoutFilter(String logoutSuccessUrl, LogoutHandler... handlers) {
        super(logoutSuccessUrl, handlers);
        logger.debug("CustomLogoutFilter(String, LogoutHandler[]) - start"); //$NON-NLS-1$

        logger.debug("CustomLogoutFilter(String, LogoutHandler[]) - end"); //$NON-NLS-1$
    }


    public CustomLogoutFilter(LogoutSuccessHandler logoutSuccessHandler, LogoutHandler... handlers) {
        super(logoutSuccessHandler, handlers);
        logger.debug("CustomLogoutFilter(LogoutSuccessHandler, LogoutHandler[]) - start"); //$NON-NLS-1$

        logger.debug("CustomLogoutFilter(LogoutSuccessHandler, LogoutHandler[]) - end"); //$NON-NLS-1$
    }
}

CustomLogoutHandler.java

/**
 * @Title: CustomLogoutHandler.java
 * @Package com.ninelephas.whale.springsecurity
 * @Description: TODO
 * Copyright: Copyright (c) 2016
 * Company:九象網絡科技(上海)有限公司
 * 
 * @author roamerxv
 * @date 2016年9月6日 下午3:38:30
 * @version V1.0.0
 */

package com.ninelephas.whale.springsecurity;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutHandler;

/**
  * @ClassName: CustomLogoutHandler
  * @Description: TODO
  * @author Comsys-roamerxv
  * @date 2016年9月6日 下午3:38:30
  *
  */

public class CustomLogoutHandler implements LogoutHandler {
    /**
     * Logger for this class
     */
    private static final Logger logger = LogManager.getLogger(CustomLogoutHandler.class.getName());

    /**

      * 創建一個新的實例 CustomLogoutHandler. 
      * <p>Title: </p>
      * <p>Description: </p>
      * @param logoutSuccessHandler
      * @param handlers
      */

    public CustomLogoutHandler() {

    }

    public void logout(HttpServletRequest request,HttpServletResponse response, Authentication authentication){
        logger.debug("logout(HttpServletRequest, HttpServletResponse, Authentication) - start"); //$NON-NLS-1$

        logger.debug("logout(HttpServletRequest, HttpServletResponse, Authentication) - end"); //$NON-NLS-1$
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章