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">logout</a>
<se:authorize access="hasRole('ROLE_ADMIN')">
<a href="${baseUrl }jsp/admin/index.jsp">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"/>