spring security 多登陆入口实现方式 以及对spring security认证流程的理解

在需求上后台管理系统 需要有一个登陆页,同时手机端也允许普通用户登录。

这个时候我设置两个http过滤器

<http auto-config="false"  pattern="/phone" entry-point-ref="authenticationEntryPoint">  
        <csrf disabled="true"/>
        <custom-filter ref="myLoginFilter"  position="FORM_LOGIN_FILTER" />  
        <logout logout-success-url="/login"/>  
    </http>  
    
    <http auto-config="true" >
        <access-denied-handler error-page="/accessDenied"/>
        <intercept-url pattern="/phone"  access="permitAll" />
        <form-login login-page="/login.jsp"
            always-use-default-target="true" authentication-failure-url="/login.jsp?error=true"
            default-target-url="/login" login-processing-url="/login_user" />
        <csrf disabled="true"/>
        <anonymous enabled="false"/>
        <!-- 增加一个filter,这点与Acegi是不一样的,不能修改默认的filter了,  这个filter位于FILTER_SECURITY_INTERCEPTOR之前  -->
        <custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/>
    </http>

这个时候FilterchanProxy里的filterchains 里会增加两个filter,一个的pattern 是/phone 一个的pattern的anyrequest。

提示:需要把anyrequest的放置在chains的末尾,也就是xml配置的时候置于最后。不然启动会报错。

 <b:bean id="myLoginFilter" class="com.kaqm.action.manage.MyUsernamePasswordAuthenticationFilter">  
        <b:property name="authenticationManager" ref="authenticationManager"/>  
        <b:property name="authenticationFailureHandler" ref="failureHandler"/> 
         <b:property name="filterProcessesUrl" value="/phone"/>   
        <b:property name="authenticationSuccessHandler" ref="successHandler"/>  
    </b:bean>  
    
       <b:bean id="authenticationEntryPoint"  
        class="com.kaqm.action.manage.MyAuthenticationEntryPoint">  
        <b:property name="loginFormUrl" value="/login.html" />  
    </b:bean> 
    <!--  end -->
    
	<!-- 一个自定义的filter,必须包含authenticationManager,accessDecisionManager,securityMetadataSource三个属性,
    	我们的所有控制将在这三个类中实现,解释详见具体配置  -->
    <b:bean id="myFilter" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
        <b:property name="authenticationManager"
            ref="authenticationManager" />
        <b:property name="accessDecisionManager"
            ref="myAccessDecisionManager" />
        <b:property name="securityMetadataSource"
            ref="mySecurityMetadataSource" />
    </b:bean>
    
    <!-- <b:bean id="acquireResourceDBInterceptor" class="com.util.security.interceptor.AcquireResourceDBInterceptor">
    </b:bean>
    <b:bean id="acquireResource" class="com.util.security.web.LeftAcquireResourceImpl">
    </b:bean> -->
   
	<!-- 验证配置 , 认证管理器,实现用户认证的入口,主要实现UserDetailsService接口即可 -->
 	<authentication-manager alias="authenticationManager"> 
	 	 
		<authentication-provider user-service-ref="userDetailsService">
			<password-encoder hash="md5">
			</password-encoder>
		</authentication-provider>
		 <!-- <authentication-provider>
		 	<user-service>
		 		<user name="zhangsan" password="zhangsan" authorities="ROLE_NORMAL"/>
		 	</user-service>
		 </authentication-provider> -->
	</authentication-manager>
	
	<!-- 项目实现的用户查询服务,将用户信息查询出来  -->
	<b:bean id="userDetailsService" class="com.util.security.support.MyUserDetailService" />

	<!-- 访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源     -->
    <b:bean id="myAccessDecisionManager"
        class="com.util.security.support.MyAccessDecisionManager">
    </b:bean>
    
    <!-- 资源源数据定义,将所有的资源和权限对应关系建立起来,即定义某一资源可以被哪些角色访问 	-->
    <b:bean id="mySecurityMetadataSource"
        class="com.util.security.support.MyInvocationSecurityMetadataSourceService">
    </b:bean>
 

这里我自己写了一个authenticationEntryPoint类 实现类为com.kaqm.action.manage.MyAuthenticationEntryPoint代码均与LoginUrlAuthenticationEntryPoint相同,只是多了一个无参构造函数

因为系统启动的时候总是提示我LoginUrlAuthenticationEntryPoint缺少一个无参数构造函数.


spring security的用户名密码验证是在MessageDigestPasswordEncoder.isPasswordValid 进行校验的。

具体流程为UsernamePasswordAuthenticationFilter 对request中的用户名密码进行提取 封装成UsernamePasswordAuthenticationToken对象,

调用AuthenticationManager 一般是ProviderManager.authenticate

调用DaoAuthenticationProvider.authenticate

调用DaoAuthenticationProvider.retriveUser

调用UserDetailService.loadUserByUsername(username)获取用户名 用户名匹配

调用DaoAuthenticationProvider.addtionalAuthenticationChekcs(user,(UsernamePasswordAuthenticationToken) authentication);

调用Md5PasswordEncoder的父类MessageDigestPassword.Encoder.isPasswordValid(String encPass,String rawPass,ObjectSalt)进行密码匹配




  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值