构建基于maven的综合项目(三)--spring security

一、添加spring security3 简单验证
    1、添加jar;
<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-core</artifactId>
			<version>${org.springframework.version}</version>
		</dependency>
		<dependency>
	        <groupId>org.springframework.security</groupId>
	        <artifactId>spring-security-web</artifactId>
	        <version>${org.springframework.version}</version>
	    </dependency>
	    <dependency>
	        <groupId>org.springframework.security</groupId>
	        <artifactId>spring-security-config</artifactId>
	        <version>${org.springframework.version}</version>
	    </dependency>

    2、web.xml添加过滤器和监听器
<!-- 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>
……
<!-- 监听session是否过期 -->
	<listener>
		<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
	</listener>

    3、引入springSecuritySimple-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<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-3.0.xsd 
		http://www.springframework.org/schema/security 
		http://www.springframework.org/schema/security/spring-security-3.0.xsd">
	<!--  
		启用安全注解和安全切点
		启用spring security的@Secured和JSR-250注解
		向类和方法添加注解,限制方法或类的访问,eg.@Secured("ROLE_TELLER")
		pre-post-annotations="enabled":基于表达式的注解形式,eg.@PreAuthorize("hasAuthority('ROLE_TELLER')")
		protect-pointcut:添加安全切点
			com.cpkf.notpad.server.impl包下所有ServiceImpl结尾的类,只有ROLE_ADMIN角色才能调用其方法
	<global-method-security 
		secured-annotations="enabled" 
		jsr250-annotations="enabled" 
		pre-post-annotations="enabled" >
		<protect-pointcut 
			access="execution(* com.cpkf.notpad.server.impl.*ServiceImpl.*(..))" 
			expression="ROLE_ADMIN"/>
	</global-method-security>
	-->
	<!--  
		auto-config:包含<form-login />、<http-basic />、<logout />三项默认配置,如果自己配置则覆盖默认配置
		access-denied-page:出错(eg没有权限)后跳转的页面,没有该属性,则抛出403错误-访问指定资源被禁止
		access-decision-manager-ref="accessDecisionManager":当角色名前缀不是ROLE_时,需要自定义访问策略管理器
	-->
	<http auto-config="true" 
		access-denied-page="/403.jsp" 
		>
		<!--  
			拦截器,设定哪些路径需要哪些权限访问
			access="ROLE_USER" 我们要保护应用程序中所有的url,只有ROLE_USER角色才能访问
			filters=true 不使用过滤器
			requires-channel:信道安全,可选any、http、https
		-->
		<intercept-url pattern="/**" access="ROLE_ADMIN" requires-channel="any"/>
		<intercept-url pattern="/login.jsp" filters="none"/>
		<intercept-url pattern="/loginError.do" filters="none"/>
		<intercept-url pattern="/redirectAddUser.do" filters="none"/>
		<intercept-url pattern="/common/**" filters="none"/>
		<intercept-url pattern="/styles/**" filters="none"/>
		<!--  
			login-page:默认登陆页面
			login-processing-url:登陆系统请求,默认j_spring_security_check
			always-use-default-target:身份验证通过后,总是跳转default-target-url
			default-target-url:成功登陆后跳转的页面
			authentication-failure-url:出错(用户名或密码不正确)后跳转页面
		-->
		<form-login login-page="/login.jsp" 
			always-use-default-target="true" 
			default-target-url="/securityLogin.do" 
			authentication-failure-url="/loginError.do" />
		<!-- 
			logout-url:退出系统请求,默认/j_spring_security_logout
			logout-success-url:成功注销后跳转的页面
			invalidate-session:退出系统时候是否报销session
		-->
		<logout logout-success-url="/login.jsp" 
			invalidate-session="true" />
		<!--  
			会话管理:在web.xml中配置监听session的监听器
			invalid-session-url:会话超时跳转请求
			session-fixation-protection="migrateSession":创建新session,并复制以前session信息
				none:什么也不做,继续使用原来的session
				newSession:创建新session,不会复制原有数据
			max-sessions:每个用户在同一时间拥有的会话数
			error-if-maximum-exceeded="true":禁止两次登陆
		-->
		<session-management 
			invalid-session-url="/sessionTimeout.do" 
			session-fixation-protection="migrateSession">
			<concurrency-control max-sessions="1" 
				error-if-maximum-exceeded="true"/>
		</session-management>
		<!-- 如果应用不是标准端口,用以下配置 
		<port-mappings>
			<port-mapping http="" https=""/>
		</port-mappings>
		-->
		<!--  
			spring security提供了一个过滤器链来提供服务,我们可以将自己的过滤器添加到过滤器链中特定位置
			position属性代替过滤器链中的过滤器,但是不能替换http自己创建使用的过滤器
				SecurityContextPersistenceFilter,ExceptionTranslationFilter或FilterSecurityInterceptor
			before和before属性插入自定义过滤器
		<custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/>
		-->
		<!--  
			基本认证,在访问被保护的资源时提示用户登陆
		-->
		<http-basic/>
	</http>
	<!-- 注入自定义加密器 -->
	<beans:bean id="md5Encoder" class="com.cpkf.notpad.security.impl.MD5EncoderImpl"/>
	<!-- 认证管理器 -->
	<authentication-manager alias="authenticationManager">
		<authentication-provider>
			<!--  
				密码加密方式,常用的有md5和sha,此处使用自定义加密器
				salt-source:盐值,为每个用户随机生成一个盐值,防止字典攻击
				可以使用UserDetailsService读取出来UserDetails对象中的属性,比如username
			-->
			<password-encoder ref="md5Encoder">
				<salt-source user-property="username"/>
			</password-encoder>
			<!--  
				方式1,使用本地数据库进行权限管理
				自定义的表结构和security默认不一致,只能用sql语句来匹配让security识别
				users-by-username-query:系统通过用户名查询登录名、密码和是否禁用状态
				authorities-by-username-query:根据用户名查找权限,在此基础上配置intercept-url
			-->
			<jdbc-user-service data-source-ref="dataSource" 
				users-by-username-query="select email,passWord,status as enabled 
					from account 
					where email = ?" 
				authorities-by-username-query="select a.email,r.roleName as authorities 
					from account a 
					join account_role ar 
						on a.account_id = ar.account_id 
					join role r 
						on r.role_id = ar.role_id 
					where a.email = ?"/>
			<!--  
				方式二,用户名和密码都写在配置文件中
			<user-service>
				<user name="[email protected]" password="B59C67BF196A4758191E42F76670CEBA" authorities="ROLE_ADMIN,ROLE_GUEST"/>
				<user name="[email protected]" password="B59C67BF196A4758191E42F76670CEBA" authorities="ROLE_GUEST"/>
			</user-service>
			-->
			<!-- 方法三,用properties文件 
			<user-service properties="/WEB-INF/conf/db/users.properties" />
			-->
		</authentication-provider>
	</authentication-manager>
</beans:beans>

users.properties
[email protected]=B59C67BF196A4758191E42F76670CEBA,ROLE_ADMIN,ROLE_GUEST
[email protected]=B59C67BF196A4758191E42F76670CEBA,ROLE_GUEST

    4、自定义加密器
package com.cpkf.notpad.security.impl;
import org.springframework.dao.DataAccessException;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import com.cpkf.notpad.commons.utils.MD5;
/**  
 * Filename:    MD5EncoderImpl.java
 * Description: 自定义加密器,需实现PasswordEncoder接口
 * Company:     
 * @author:     Jiang.hu
 * @version:    1.0
 * Create at:   May 24, 2011 4:35:56 PM
 * modified:    
 */
public class MD5EncoderImpl implements  PasswordEncoder {
	/* 
	 * method name   : encodePassword
	 * description   : 获得加密密码
	 * @author       : Jiang.Hu
	 * modified      : leo ,  May 24, 2011
	 * @see          : @see org.springframework.security.authentication.encoding.PasswordEncoder#encodePassword(java.lang.String, java.lang.Object)
	 */    
	public String encodePassword(String rawPass, Object salt) throws DataAccessException {
		return MD5.getMD5ofStr(rawPass);
	}
	/* 
	 * method name   : isPasswordValid
	 * description   : 验证密码
	 * @author       : Jiang.Hu
	 * modified      : leo ,  May 24, 2011
	 * @see          : @see org.springframework.security.authentication.encoding.PasswordEncoder#isPasswordValid(java.lang.String, java.lang.String, java.lang.Object)
	 */    
	public boolean isPasswordValid(String encPass, String rawPass, Object salt) throws DataAccessException {
		return encPass.equals(encodePassword(rawPass, salt));
	}
}

    5、login.jsp
<!--  
			/j_spring_security_check:提交到spring security验证中心
			${sessionScope['SPRING_SECURITY_LAST_USERNAME']}:使用最后一次登陆的用户名
			_spring_security_remember_me:记住我
		-->
		<div>
			<font color="red">
				login error:<br/>
				${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}
			</font>
		</div>
		<form id="form2" action="<c:url value='/j_spring_security_check' />" method="post">
			<spring:message code="message.login.email"/>
			<input type="text" id="j_username" name="j_username" value="${sessionScope['SPRING_SECURITY_LAST_USERNAME']}"/><br/>
			<spring:message code="message.login.password"/>:</label>
			<input type="password" id="j_password" name="j_password"/><br/>
			<input type="checkbox" name="_spring_security_remember_me" />
			<spring:message code="message.login.keepLogin"/><br/>
			<input type="submit" value="<spring:message code='message.login.login'/>" />
		</form>

    安全退出:
<a href="<c:url value='/j_spring_security_logout' />"><spring:message code="security.logout"/></a>

    6、这样就实现了简单的security验证授权功能,但是这种方式并不完善:
        和自定义url资源库没有绑定,我们应该将每一个请求的url和资源库比对,找出访问该url的角色有哪些,再根据用户的角色来授权该用户是否能访问
    [email protected]用户拥有ROLE_ADMIN角色,在登录访问"/securityLogin.do"url时,如果resource资源库中"/securityLogin.do"没有ROLE_ADMIN角色,该用户没有权限权限,应跳转到403页面,如果resource资源库中"/securityLogin.do"有ROLE_ADMIN角色,该用户才能访问。但是,这篇配置使用的是默认的过滤器链进行服务,是达不到这种效果的,它只能通过数据库用户验证和intercept-url配置进行简单授权,要想达到这种效果,只有自定义过滤器,下章详细讲解。

    7、附件中提供Spring Security-3.0.1 中文官方文档下载。

你可能感兴趣的:(java,spring,maven,Security,项目管理)