天天看点

Spring Security3 实践

Spring Security还是很强大的,即支持粗粒度的访问控制,还能支持精确到web元素的的控制。

首先,spring配置中添加对security的支持:

<!-- security configurations begin -->
	<security:http pattern="/login.jsp*" security="none"/>
	<security:http pattern="/jsp/js/**" security="none"/>
	<security:http pattern="/jsp/css/**" security="none"/>
	
	<!-- use-expressions='true' needs 'access' to be 'hasRole(role)' -->
	<!-- use-expression is optional,when u not use this, hasRole() can not be used neither. -->
	<security:http access-denied-page="/denied.jsp" use-expressions="true">
		<security:intercept-url pattern="/jsp/admin/**" access="hasRole('ROLE_ADMIN')"/>
		<security:intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
		<security:logout delete-cookies="true" logout-url="/do_logout"/>
		<security:form-login login-page="/login.jsp" login-processing-url="/do_security_check"
			authentication-failure-url="/login.jsp?error=t"
			default-target-url="/viewAllContacts.do"/>
		<!-- <security:remember-me key="contact_key" token-validity-seconds="600"/> -->
		<security:remember-me key="contact_key" data-source-ref="dataSource" token-validity-seconds="30"/>
	</security:http>
	
	<security:authentication-manager>
		<security:authentication-provider>
			<security:password-encoder hash="md5"/>
			
			<security:jdbc-user-service data-source-ref="dataSource" 
				users-by-username-query="select name_f,password_f,status_f from user_t where name_f=?"
				authorities-by-username-query="select user_f,role_f from user_role_t where user_f=?"/>
			 
			 <!--
			<security:user-service>
				<security:user name="admin" password="21232f297a57a5a743894a0e4a801fc3" authorities="ROLE_USER,ROLE_ADMIN"/>
				<security:user name="hello" password="5d41402abc4b2a76b9719d911017c592" authorities="ROLE_USER"/>
			</security:user-service>
			 -->
		</security:authentication-provider>
	</security:authentication-manager>
	<!-- security configuratios end -->
           

其中定义了角色ROLE_ADMIN和ROLE_USER都能访问所有资源,但是只有ROLE_ADMIN能访问基于url为/jsp/admin/* 的资源。

如果form-login不做配置,则如果访问被拒绝的时候,会跳转到spring提供的一个login form。

form-login中 login-processing-url 配置的路径必须和web form中提交的url一致。

其中user-service配置了两种:

1.被注释掉的是基于jdbc的,这需要在数据库中创建几张表:

mysql> desc user_t;

+------------+--------------+------+-----+---------+----------------+

| Field      | Type         | Null | Key | Default | Extra          |

+------------+--------------+------+-----+---------+----------------+

| id_f       | int(11)      | NO   | PRI | NULL    | auto_increment |

| name_f     | varchar(100) | YES  |     | NULL    |                |

| password_f | varchar(32)  | YES  |     | NULL    |                |

| status_f   | int(11)      | YES  |     | 1       |                |

+------------+--------------+------+-----+---------+----------------+

mysql> desc role_t;

+----------+--------------+------+-----+---------+----------------+

| Field    | Type         | Null | Key | Default | Extra          |

+----------+--------------+------+-----+---------+----------------+

| id_f     | int(11)      | NO   | PRI | NULL    | auto_increment |

| name_f   | varchar(100) | YES  |     | NULL    |                |

| status_f | int(11)      | YES  |     | 1       |                |

+----------+--------------+------+-----+---------+----------------+

mysql> desc user_role_t;

+--------+--------------+------+-----+---------+----------------+

| Field  | Type         | Null | Key | Default | Extra          |

+--------+--------------+------+-----+---------+----------------+

| id_f   | int(11)      | NO   | PRI | NULL    | auto_increment |

| user_f | varchar(100) | NO   |     |         |                |

| role_f | varchar(100) | NO   |     |         |                |

+--------+--------------+------+-----+---------+----------------+

2.第二种基于配置文件的用户名密码管理,密码是md5加密的

下面是login form:

<s:url var="authUrl" value="/do_security_check"/>
	<div id="login_box">
	<h3>Login for Contact</h3>
	<p class="error">${param.error=="t"?"authentication failed!":"" }</p>
	<form action="${authUrl }" method="post">
		<p>
			<label for="username">Username:</label>
			<input id="username" name="j_username" class="ipt"/>
		</p>
		<p>
			<label for="password">Password:</label>
			<input id="password" name="j_password" type="password" class="ipt"/>
		</p>
		<p>
			<input id="remember_me" type="checkbox" name="_spring_security_remember_me"/>
			<label for="remember_me">remember me?</label>
		</p>
		<p><input type="submit" value="login" class="btn"/></p>
	</form>
	</div>
           

如果直接访问某个未授权的资源,会弹回这个登录页面,密码验证成功之后,跳转到之前访问的资源页面。

如果想指定web中某个按钮或者链接只在登录者具有admin权限的时候显示,可以这样:

<div style="width:500px;text-align:right">
				<spring:url var="baseUrl" value="/"/>
				welcome,<span style="color:blue;"><se:authentication property="principal.username"/></span>
				<a href="${baseUrl }do_logout" target="_blank" rel="external nofollow" >logout</a> 
				<se:authorize access="hasRole('ROLE_ADMIN')">
					<a href="${baseUrl }jsp/admin/index.jsp" target="_blank" rel="external nofollow" >admin</a>
				</se:authorize>
			</div>
           

下面是使用到的标签申明:

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="se" %>
           

如果想使用https协议访问admin相关资源,可以这样:

首先,在修改security配置:

<security:intercept-url pattern="/jsp/admin/**" requires-channel="https" access="hasRole('ROLE_ADMIN')"/>
		<security:intercept-url pattern="/**" access="hasRole('ROLE_USER')" requires-channel="http"/>
           

然后,修改tomcat配置文件server.xml

<Connector protocol="org.apache.coyote.http11.Http11NioProtocol"   
           port="8443" minSpareThreads="5" maxSpareThreads="75"   
           enableLookups="true" disableUploadTimeout="true"     
           acceptCount="100"  maxThreads="200"   
           scheme="https" secure="true" SSLEnabled="true"   
           clientAuth="false" sslProtocol="TLS"   
           keystoreFile="d:\server.key"     
           keystorePass="admins"/>
           

Tomcat6.0.35 security connection(https) 配置

继续阅读