文档章节

spring-security 多类型用户登录+登录多参数验证

w
 wangxinxx
发布于 2017/03/26 06:01
字数 1917
阅读 858
收藏 0

如果一个系统分为前台用户和后台用户那么就不能使用spring-security的默认配置了。 需要自己来分开配置两种用户的登录方式。

首先创建spring-disuser-security.xml 与 spring-etuser-security.xml 两个配置文件,分别来配置两种用户登录的权限与验证方式

spring-disuser-security.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:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context" 
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:security="http://www.springframework.org/schema/security" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
		http://www.springframework.org/schema/aop 
		http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
		http://www.springframework.org/schema/tx 
		http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-3.0.xsd
		http://www.springframework.org/schema/security   
        http://www.springframework.org/schema/security/spring-security-3.1.xsd">
        
        <!-- 使用自定义Filter时需要将http节点的auto-config="true"属性删除,并且要通过entry-point-ref指定一个入口  -->
        <security:http use-expressions="true" access-denied-page="/powermiss.jsp" 
     	  	authentication-manager-ref="disuserAuthManager" name="disuserSecurity" 
     	  	entry-point-ref="authenticationEntryPoint">
        	<security:intercept-url pattern="/disuserlogin.jsp"  access="permitAll"/>
        	<!-- 配置自定义的Filter,并且将其放在FORM_LOGIN_FILTER节点,就会替换掉原来的FORM_LOGIN_FILTER节点  -->
        	<security:custom-filter ref="loginProcessFilter" position="FORM_LOGIN_FILTER"/>  
        </security:http>  
           
	    <security:authentication-manager id="disuserAuthManager" >  
	        <security:authentication-provider user-service-ref="DisuserserDetailService" />
	    </security:authentication-manager>   
		
		<!-- 登录处理Filter  -->
		<bean id="loginProcessFilter" class="com.tuanfang.service.DisUsernamePasswordAuthenticationFilter">
			<property name="loginid" value="loginid" />
			<property name="yzm" value="yzm" />
			<property name="usernameParameter" value="username" />  
			<property name="passwordParameter" value="password" />
			<property name="filterProcessesUrl" value="/disuserlogin.htm" />
			<property name="authenticationManager" ref="disuserAuthManager" />
			<property name="authenticationSuccessHandler" ref="successHandler" />
			<property name="authenticationFailureHandler" ref="failureHandler" />
		</bean>		
		
		<!-- 登录成功处理 -->
		<bean id="successHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
			<property name="defaultTargetUrl" value="/index.jsp" />
			<property name="alwaysUseDefaultTargetUrl" value="true" />
		</bean>
		
		<!-- 登录失败处理 -->
		<bean id="failureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
		 	 <property name="defaultFailureUrl" value="/disuserlogin.jsp?error=true" />
		</bean>
		
	  <!-- 登录入口 --> 
	   <bean id="authenticationEntryPoint"  
	        class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">  
	        <property name="loginFormUrl" value="/disuserlogin.jsp" />  
       </bean>  
</beans>


 

 

接下来编写DisUsernamePasswordAuthenticationFilter.java文件,处理用户登录。

spring-security默认的处理登录的类是org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter,可以将其中的代码复制到自己写的DisUsernamePasswordAuthenticationFilter.java文件中。

然后在进行自己的修改,达到验证验证码,与公司登录id的验证。

 

/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.tuanfang.service;


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

import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.util.Assert;


/**
 * Processes an authentication form submission. Called {@code AuthenticationProcessingFilter} prior to Spring Security
 * 3.0.
 * <p>
 * Login forms must present two parameters to this filter: a username and
 * password. The default parameter names to use are contained in the
 * static fields {@link #SPRING_SECURITY_FORM_USERNAME_KEY} and {@link #SPRING_SECURITY_FORM_PASSWORD_KEY}.
 * The parameter names can also be changed by setting the {@code usernameParameter} and {@code passwordParameter}
 * properties.
 * <p>
 * This filter by default responds to the URL {@code /j_spring_security_check}.
 *
 * @author Ben Alex
 * @author Colin Sampaleanu
 * @author Luke Taylor
 * @since 3.0
 */
public class DisUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
    //~ Static fields/initializers =====================================================================================

    public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
    public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";
    public static final String SPRING_SECURITY_FORM_YZM_KEY = "yzm";
    public static final String SPRING_SECURITY_FORM_LOGINID_KEY = "loginid";
    public static final String USERNAME_LOGINID_SPLIT = "/";
    /**
     * @deprecated If you want to retain the username, cache it in a customized {@code AuthenticationFailureHandler}
     */
    @Deprecated
    public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";

    private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
    private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
    private String yzm = SPRING_SECURITY_FORM_YZM_KEY;
    private String loginid = SPRING_SECURITY_FORM_LOGINID_KEY;
    private boolean postOnly = true;

    //~ Constructors ===================================================================================================

    public DisUsernamePasswordAuthenticationFilter() {
        super("/j_spring_security_check");
    }

    //~ Methods ========================================================================================================

    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }

        String username = obtainUsername(request);
        String password = obtainPassword(request);
        String loginid = obtainLoginid(request);
        String yzm = obtainYzm(request);
        
        if (username == null) {
            username = "";
        }

        if (password == null) {
            password = "";
        }
        
        if (loginid == null) {
        	loginid = "";
        }
        
        if (yzm == null) {
        	yzm = "";
        }

        username = username.trim();
        password = password.trim();
        loginid = loginid.trim();
        yzm = yzm.trim();
        
        username = loginid + USERNAME_LOGINID_SPLIT + username ;   //将公司登录id与登录用户名使用 / 连接起来

        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);

        // Allow subclasses to set the "details" property
        setDetails(request, authRequest);

        return this.getAuthenticationManager().authenticate(authRequest);
    }

    /**
     * Enables subclasses to override the composition of the password, such as by including additional values
     * and a separator.<p>This might be used for example if a postcode/zipcode was required in addition to the
     * password. A delimiter such as a pipe (|) should be used to separate the password and extended value(s). The
     * <code>AuthenticationDao</code> will need to generate the expected password in a corresponding manner.</p>
     *
     * @param request so that request attributes can be retrieved
     *
     * @return the password that will be presented in the <code>Authentication</code> request token to the
     *         <code>AuthenticationManager</code>
     */
    protected String obtainPassword(HttpServletRequest request) {
        return request.getParameter(passwordParameter);
    }
    
    //获取验证码
    protected String obtainYzm(HttpServletRequest request){
    	   return request.getParameter(yzm);
    }
    
    //获取公司id
    protected String obtainLoginid(HttpServletRequest request){
    	   return request.getParameter(loginid);
    }
    
    
    
    /**
     * Enables subclasses to override the composition of the username, such as by including additional values
     * and a separator.
     *
     * @param request so that request attributes can be retrieved
     *
     * @return the username that will be presented in the <code>Authentication</code> request token to the
     *         <code>AuthenticationManager</code>
     */
    protected String obtainUsername(HttpServletRequest request) {
        return request.getParameter(usernameParameter);
    }

    /**
     * Provided so that subclasses may configure what is put into the authentication request's details
     * property.
     *
     * @param request that an authentication request is being created for
     * @param authRequest the authentication request object that should have its details set
     */
    protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
        authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
    }

    /**
     * Sets the parameter name which will be used to obtain the username from the login request.
     *
     * @param usernameParameter the parameter name. Defaults to "j_username".
     */
    public void setUsernameParameter(String usernameParameter) {
        Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
        this.usernameParameter = usernameParameter;
    }

    /**
     * Sets the parameter name which will be used to obtain the password from the login request..
     *
     * @param passwordParameter the parameter name. Defaults to "j_password".
     */
    public void setPasswordParameter(String passwordParameter) {
        Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
        this.passwordParameter = passwordParameter;
    }

    /**
     * Defines whether only HTTP POST requests will be allowed by this filter.
     * If set to true, and an authentication request is received which is not a POST request, an exception will
     * be raised immediately and authentication will not be attempted. The <tt>unsuccessfulAuthentication()</tt> method
     * will be called as if handling a failed authentication.
     * <p>
     * Defaults to <tt>true</tt> but may be overridden by subclasses.
     */
    public void setPostOnly(boolean postOnly) {
        this.postOnly = postOnly;
    }

    public final String getUsernameParameter() {
        return usernameParameter;
    }

    public final String getPasswordParameter() {
        return passwordParameter;
    }

	public String getYzm() {
		return yzm;
	}

	public void setYzm(String yzm) {
		this.yzm = yzm;
	}

	public String getLoginid() {
		return loginid;
	}

	public void setLoginid(String loginid) {
		this.loginid = loginid;
	}
}


 

 

接下来编写提供Disuser的UserDetailsService类

 

package com.tuanfang.service;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Repository;

import com.tuanfang.dao.impl.DisuserDaoImpl;
import com.tuanfang.dao.impl.SysPowrDaoImpl;
import com.tuanfang.pojo.Disuser;
import com.tuanfang.pojo.SysPower;

@Repository("DisuserserDetailService")  
public class DisuserserDetailService implements UserDetailsService{
	
	@Resource(name="DisuserDaoImpl")
	private DisuserDaoImpl disuserDao ;
	
	@Resource(name="SysPowrDaoImpl")
	private SysPowrDaoImpl sysPowrDao ;

	@Override
	public UserDetails loadUserByUsername(String usernameAndloginId)
			throws UsernameNotFoundException {
		//将公司登录id与登录用户名使用/分开
		String args[]  = usernameAndloginId.split(DisUsernamePasswordAuthenticationFilter.USERNAME_LOGINID_SPLIT);
		String loginid = args[0];
		String username = args[1];
		Disuser disuser =  disuserDao.findByLoginIdAndUserName(loginid , username);
		UserDetails userDetail = null ;
		if(disuser != null){
			userDetail = new User(username, disuser.getPassword(),disuser.getStatus() ==Disuser.ENABLE ,
					true, true, true, obtainUserPowers(disuser.getId()));
		}
		return userDetail;
	}
	
	public Collection<GrantedAuthority> obtainUserPowers(BigInteger userId){
		Collection<GrantedAuthority> gas = new ArrayList<GrantedAuthority>();
		List<SysPower> powers = sysPowrDao.findDisuserPowers(userId);
		if(powers != null && powers.size() > 0){
			for (SysPower sysPower : powers) {  
				gas.add(new SimpleGrantedAuthority(sysPower.getCode()));   
			}
		}
		gas.add(new SimpleGrantedAuthority("HAVE_LOGIN"));	//登录    
		return gas ;
	}

}


 

 

登录页面disuserlogin.jsp

 

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<%  
String path = request.getContextPath();  
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  
%>  
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>DisuserLogin</title>
</head>
<body>
     
	<form action="<%=basePath %>disuserlogin.htm" method="post">      
        <p> 
            <label for="username">Username</label> <input id="username"    
                name="username" type="text" />    
        </p>    
    
        <p>    
            <label for="password">password</label> <input id="password"    
                name="password" type="password" />            
        </p>    
          
    
        <p>    
            <label for="loginid">LoginId</label> <input id="loginid"    
                name="loginid" type="text" />            
        </p>    
          
    
        <p>    
            <label for="yzm">验证码</label> <input id="yzm"    
                name="yzm" type="text" />            
        </p>    
          
        <input type="submit" value="Login" /> 
    </form>    
	
	  
</body>
</html>


 

 

 

 

这样就配置好了Disuser的login
 

 

 

接下来配置EtdsUser的login。只需要username与password

spring-etuser-security.xml文件内容如下(使用spring-security默认的方式配置):

 

<?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:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context" 
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:security="http://www.springframework.org/schema/security" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
		http://www.springframework.org/schema/aop 
		http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
		http://www.springframework.org/schema/tx 
		http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-3.0.xsd
		http://www.springframework.org/schema/security   
        http://www.springframework.org/schema/security/spring-security-3.1.xsd">
        
        <security:http auto-config="true" pattern="/admin/**" use-expressions="true" access-denied-page="/powermiss.jsp" 
        authentication-manager-ref="etuserAuthManager" name="etuserSecurity">
        	<security:intercept-url pattern="/admin/etuserlogin.jsp"  access="permitAll"/>
        	<security:form-login login-processing-url="/admin/j_spring_security_check" authentication-failure-url="/admin/etuserlogin.jsp?error=true"  login-page="/admin/etuserlogin.jsp" 
        		 default-target-url="/index.jsp" />
        </security:http>  
           
        
	    <security:authentication-manager id="etuserAuthManager" >  
	        <security:authentication-provider user-service-ref="EtuserDetailService"/>
	    </security:authentication-manager>   
		
	
</beans>


Etdsuser的UserDetailsService类如下:

 

 

package com.tuanfang.service;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Repository;

import com.tuanfang.dao.impl.EtdsuserDaoImpl;
import com.tuanfang.dao.impl.SysPowrDaoImpl;
import com.tuanfang.pojo.EtdsUser;
import com.tuanfang.pojo.SysPower;

@Repository("EtuserDetailService")  
public class EtuserDetailService implements UserDetailsService{
	
	@Resource(name="EtdsuserDaoImpl")
	private EtdsuserDaoImpl etdsuserDao ;
	
	@Resource(name="SysPowrDaoImpl")
	private SysPowrDaoImpl sysPowrDao ;

	@Override
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException {
		EtdsUser etuser =  etdsuserDao.findUserByLoginName(username);
		UserDetails userDetail = null ;
		if(etuser != null){
			userDetail = new User(username, etuser.getPassword(),etuser.getStatus() ==EtdsUser.ENABLE ,
					true, true, true, obtainUserPowers(etuser.getId()));  
		}
		return userDetail;
	}
	
	public Collection<GrantedAuthority> obtainUserPowers(BigInteger userId){
		Collection<GrantedAuthority> gas = new ArrayList<GrantedAuthority>();
		List<SysPower> powers = sysPowrDao.findEtuserPowers(userId);
		if(powers != null && powers.size() > 0){
			for (SysPower sysPower : powers) {  
				gas.add(new SimpleGrantedAuthority(sysPower.getCode()));   
			}
		}
		gas.add(new SimpleGrantedAuthority("HAVE_LOGIN"));	//登录   
		return gas ;
	}

}


然后在applicationContext.xml中导入spring-disuser-security.xml与spring-etuser-security.xml

 


<import resource="spring-etuser-security.xml"/>
<import resource="spring-disuser-security.xml"/>

本文转载自:http://lib.csdn.net/article/javaee/2622

w
粉丝 10
博文 59
码字总数 17566
作品 0
呼和浩特
程序员
私信 提问
Spring Security 快速了解

在Spring Security之前 我曾经使用 实现了一个简单网站Demo的登录拦截和Session处理工作,虽然能够实现相应的功能,但是无疑Spring Security提供的配置方法更加简单明确,能够更好的保护Web...

Rekent
2018/08/10
0
0
Spring+Shiro案例分析

在 Web 项目中应用 Apache Shiro Apache Shiro 是功能强大并且容易集成的开源权限框架,它能够完成认证、授权、加密、会话管理等功能。认证和授权为权限控制的核心,简单来说,“认证”就是证...

程序界小强
01/08
0
0
SpringBoot集成Spring Security(4)——自定义表单登录

通过前面三篇文章,应该大致了解了Spring Security的流程。你应该发现了,真正的登录请求是由Spring Security帮我们处理的,那么我们如何实现自定义表单登录呢,比如添加一个验证码… 源码地...

yuanlaijike
2018/05/09
0
0
SpringBoot之整合Spring Security,为自己的系统提供安全保障

需求: 1.权限控制:角色有多种角色,每个角色对应多个用户,每个角色又对应不同的菜单权限 2.资源控制: ①有些地址只能当用户登录之后才能访问 ②有些地址可以对无状态用户开放,例如API ③对...

数据加载中
2018/05/08
0
0
Spring boot 前后台分离项目 怎么处理spring security 抛出的异常

最近在开发一个项目 前后台分离的 使用 spring boot + spring security + jwt 实现用户登录权限控制等操作。但是 在用户登录的时候,怎么处理spring security 抛出的异常呢?使用了@RestCont...

developlee的潇洒人生
2018/05/07
2.3K
3

没有更多内容

加载失败,请刷新页面

加载更多

代理模式之JDK动态代理 — “JDK Dynamic Proxy“

动态代理的原理是什么? 所谓的动态代理,他是一个代理机制,代理机制可以看作是对调用目标的一个包装,这样我们对目标代码的调用不是直接发生的,而是通过代理完成,通过代理可以有效的让调...

code-ortaerc
36分钟前
4
0
学习记录(day05-标签操作、属性绑定、语句控制、数据绑定、事件绑定、案例用户登录)

[TOC] 1.1.1标签操作v-text&v-html v-text:会把data中绑定的数据值原样输出。 v-html:会把data中值输出,且会自动解析html代码 <!--可以将指定的内容显示到标签体中--><标签 v-text=""></......

庭前云落
今天
7
0
VMware vSphere的两种RDM磁盘

在VMware vSphere vCenter中创建虚拟机时,可以添加一种叫RDM的磁盘。 RDM - Raw Device Mapping,原始设备映射,那么,RDM磁盘是不是就可以称作为“原始设备映射磁盘”呢?这也是一种可以热...

大别阿郎
今天
10
0
【AngularJS学习笔记】02 小杂烩及学习总结

本文转载于:专业的前端网站☞【AngularJS学习笔记】02 小杂烩及学习总结 表格示例 <div ng-app="myApp" ng-controller="customersCtrl"> <table> <tr ng-repeat="x in names | orderBy ......

前端老手
昨天
14
0
Linux 内核的五大创新

在科技行业,创新这个词几乎和革命一样到处泛滥,所以很难将那些夸张的东西与真正令人振奋的东西区分开来。Linux内核被称为创新,但它又被称为现代计算中最大的奇迹,一个微观世界中的庞然大...

阮鹏
昨天
18
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部