首页 > 如何spring security4.0.2中自定义登录验过滤器实现?

如何spring security4.0.2中自定义登录验过滤器实现?

因为一些原因,我需要自定义自己的UsernamePasswordAuthenticationFilter,之后把<form-login>标签去掉了,然后<session> <logout><session>等标签之间的配合好像都失效了?然后就把这几个过滤器都重自定义一下。需要自定义其它过滤器吗? 我需要一个过滤器或者其它相关过滤器的配置。在自定义登录验证过滤器之后,<session>,<logout>等标签配置好像失效了。这正常吗?
这里是一个问题:是不是自定义UsernamePasswordAuthenticationFilter之后相关的这几个过滤器都必须实现,而不能再继续使用<logout>等标签了。

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

    <http auto-config="false" entry-point-ref="loginUrlAuthenticationEntryPoint">
    <csrf disabled="true"/>
        <intercept-url pattern="/login.html" access="permitAll"/>
        <intercept-url pattern="/resources/**" access="permitAll" />
        <intercept-url pattern="/about" access="permitAll" />
        <intercept-url pattern="/login" access="permitAll"/>
        <intercept-url pattern="/user/**" access="hasRole('USER')" />
        <intercept-url pattern="/admin/**" access="hasRole('ADMIN')" />
        <!-- 这个要在最后一个拦截,否则会匹配上,/user,/admin都将失效(未验证) -->
        <intercept-url pattern="/**" access="hasRole('USER')" />
        <access-denied-handler error-page="/accessDenide" />
        <!-- <session-management session-fixation-protection="migrateSession"> 
            <concurrency-control max-sessions="1" expired-url="/login?error=expired" 
            /> </session-management> -->
        <custom-filter ref="ipFilter" before="FILTER_SECURITY_INTERCEPTOR" />
        <custom-filter ref="concurrencyFilter" position="CONCURRENT_SESSION_FILTER" />
        <custom-filter ref="usernamePasswordAuthenticationFilter"
            position="FORM_LOGIN_FILTER" />
        <custom-filter ref="rememberMeFilter" position="REMEMBER_ME_FILTER" />
        <custom-filter ref="logoutFilter" position="LOGOUT_FILTER" />

        <!-- <remember-me key="Bay1ts" remember-me-parameter="remember-me" token-validity-seconds="604800" 
            data-source-ref="dataSource" user-service-ref="customjdbcUserService" /> 
            <form-login login-page="/login" default-target-url="/" password-parameter="pwd" 
            /> <logout logout-success-url="/about" logout-url="/logout"/> -->
    </http>

    <!-- 注意这里,<beans:bean id="">的写法 -->
    <!-- 注意这里这些属性,其实可以不设置的,本来里面就有static的这些String,表示默认的,但如果你的数据库不是这样的模式,就该自己指定了,像这样。 -->
    <!-- 因为配置了passwordEncoder,导致输入的密码到数据库比较时都已经是加密过的了,这个是为了在启动时把数据库里的密码加密一下就能匹配了。 -->
    <!-- 只能运行一次,不然会把密文再加密一次 -->

    <!-- 明文密码加密加盐器!!!!!! -->
    <!-- <beans:bean class="com.bay1ts.security.DatebasePasswordSecurityUpdater" 
        init-method="secureDatabase" depends-on="dataSource"> <beans:property name="dataSource" 
        ref="dataSource" /> </beans:bean> -->
    <beans:bean id="concurrencyFilter"
        class="org.springframework.security.web.session.ConcurrentSessionFilter">
        <beans:constructor-arg name="sessionRegistry"
            ref="sessionRegistry" />
        <beans:constructor-arg name="expiredUrl"
            value="/login?error=expired" />
    </beans:bean>
    <beans:bean id="sessionRegistry"
        class="org.springframework.security.core.session.SessionRegistryImpl" />
    <beans:bean id="http403EntryPoint"
        class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint">
    </beans:bean>
    <beans:bean id="loginUrlAuthenticationEntryPoint"
        class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
        <beans:constructor-arg name="loginFormUrl"
            value="/login.html" />
    </beans:bean>
    <beans:bean id="sas"
        class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy">
        <!-- 
        <beans:constructor-arg>
            <beans:list>
                <beans:bean
                    class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
                    <beans:constructor-arg ref="sessionRegistry" />
                    <beans:property name="maximumSessions" value="1" />
                    <beans:property name="exceptionIfMaximumExceeded"
                        value="true" />
                </beans:bean>
                <beans:bean
                    class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy">
                </beans:bean>
                <beans:bean
                    class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy">
                    <beans:constructor-arg ref="sessionRegistry" />
                </beans:bean>
            </beans:list>
        </beans:constructor-arg>
         -->
         <beans:property name="migrateSessionAttributes" value="true"/>
    </beans:bean>
    <beans:bean id="rememberMeFilter"
        class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
        <beans:constructor-arg name="authenticationManager"
            ref="authenticationManager" />
        <beans:constructor-arg name="rememberMeServices"
            ref="rememberMeServices" />
    </beans:bean>
    <beans:bean id="usernamePasswordAuthenticationFilter"
        class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
        <beans:property name="rememberMeServices" ref="rememberMeServices" />
        <beans:property name="authenticationManager" ref="authenticationManager" />
        <beans:property name="filterProcessesUrl" value="/login" />
        <beans:property name="authenticationFailureHandler"
            ref="failureHandler" />
        <beans:property name="authenticationSuccessHandler"
            ref="successHandler" />
        <beans:property name="sessionAuthenticationStrategy"
            ref="sas" />
    </beans:bean>
    <beans:bean id="successHandler"
        class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
        <beans:property name="defaultTargetUrl" value="/" />
    </beans:bean>
    <beans:bean id="failureHandler"
        class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
        <beans:property name="defaultFailureUrl" value="/login.html" />
    </beans:bean>
    <beans:bean id="logoutHandler"
        class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
    <beans:bean id="logoutFilter"
        class="org.springframework.security.web.authentication.logout.LogoutFilter">
        <beans:constructor-arg name="logoutSuccessUrl"
            value="/" />
        <beans:constructor-arg>
            <beans:array>
                <beans:ref local="logoutHandler" />
                <beans:ref local="rememberMeServices" />
            </beans:array>
        </beans:constructor-arg>
        <beans:property name="filterProcessesUrl" value="/logout" />
    </beans:bean>
    <beans:bean id="rememberMeServices"
        class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
        <beans:constructor-arg name="key" value="Bay1ts" />
        <beans:constructor-arg name="userDetailsService"
            ref="customjdbcUserService" />
        <beans:constructor-arg name="tokenRepository"
            ref="tokenRepository" />
    </beans:bean>
    <beans:bean id="tokenRepository" class="com.bay1ts.security.CustomTokenRepository">
        <beans:property name="dataSource" ref="dataSource" />
    </beans:bean>
    <beans:bean id="rememberMeAuthenticationProvider"
        class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
        <beans:constructor-arg name="key" value="Bay1ts" />
    </beans:bean>
    <beans:bean id="customjdbcUserService" class="com.bay1ts.security.CustomJdbcDaoImpl">
        <beans:property name="dataSource" ref="dataSource" />
    </beans:bean>
    <beans:bean id="passwordEncoder"
        class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" />
    <beans:bean id="saltSource"
        class="org.springframework.security.authentication.dao.ReflectionSaltSource">
        <beans:property name="userPropertyToUse" value="username" />
    </beans:bean>
    <beans:bean id="ipFilter"
        class="com.bay1ts.security.IPRoleAuthenticationFilter">
        <beans:property name="targetRole" value="ADMIN" />
        <beans:property name="allowedIPAddresses">
            <beans:list>
                <beans:value>0:0:0:0:0:0:0:1</beans:value>
            </beans:list>
        </beans:property>
    </beans:bean>
    <authentication-manager alias="authenticationManager">
        <authentication-provider user-service-ref="customjdbcUserService">
            <password-encoder ref="passwordEncoder">
                <salt-source ref="saltSource" />
            </password-encoder>
        </authentication-provider>
        <authentication-provider ref="rememberMeAuthenticationProvider" />
    </authentication-manager>
</beans:beans>

之后
login.html的主要部分:

<form action="/login" method=post>
      <div class="input-container">
        <input type="text" id="Username" name="username" required="required"/>
        <label for="用户名">Username</label>
        <div class="bar"></div>
      </div>
      <div class="input-container">
        <input type="password" id="Password" name="password" required="required"/>
        <label for="密码">Password</label>
        <div class="bar"></div>
      </div>
      <div class="checkbox">
        <input type="checkbox" id="Remember-me" name="remember-me"/>
        <label for="Remember-me">Remember-me</label>
        <div class="checkbox"></div>
      </div>
      <div class="button-container">
        <button><span>Go</span></button>
      </div>
      <div class="footer"><a href="#">忘记密码?</a></div>
      <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
    </form>
    

这是basecontroller

@RequestMapping("/login")
    public void login(){
        
    }
    @RequestMapping(value="/login",params="error")
    public String login(@RequestParam("error")String error,Model model){
        model.addAttribute("errormsg", error);
        return "error_expired";
    }
    @RequestMapping("/about")
    public String about(){
        return "about";
    }
    @ModelAttribute("numUsers")
    public int getNumberOfCurrentUsers(){
        System.out.println(SessionRegistry);
        for(Object o:SessionRegistry.getAllPrincipals()){
            System.out.println(o.toString());
        }
        return SessionRegistry.getAllPrincipals().size();
    }

这是web.xml相关部分

<listener>
        <listener-class>
            org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
    </listener>
<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>

并且我禁用了csrf功能,如果不禁用的话说网页包含循环定向。
但是现在,我觉着应该对session(会话)的处理还有很大缺陷,因为/index下有统计当前已登录用户数量的功能,现在一直是0,并且session的并发控制失效了,在另外一浏览器上登陆时不能顶下去原来登陆的用户了。所以现在的问题,大概就是csrf问题,和session的问题了。
希望大家指导一下大三党,弄了好久了,在这样下去效率太低了。多谢大家啦!

【热门文章】
【热门文章】