《Spring实战3》第九章 保护Spring应用

Spring Security是一种基于SpringAOP和Servlet过滤器实现的安全框架。

Spring Security介绍

Spring Security是为基于Spring的应用程序提供声明式安全保护的安全框架。Spring Security提供了完整的安全性解决方案,它能够在Web请求级别和方法调用级别处理身份验证和授权。因为基于Spring框架,所以Spring Security充分利用了依赖注入和面向切面的技术。
Spring Security从两个角度来解决安全性问题。它使用Servlet过滤器保护Web请求并限制URL级别的访问,也可以使用SpringAOP保护方法调用——借助与对象代理和使用通知,能够确保只有具备适当权限的用户才能访问安全保护的方法。

Spring Security 起步

Spring Security3.0分为了8个模块。应用程序类路径下至少要包含核心和配置两个模块。Spring Securiy用于保护Web需要添加Web模块。Spring Security的JSP标签库需要添加Tag Library模块。
在这里插入图片描述

使用Spring Security配置命名空间

<?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-4.3.xsd
                        http://www.springframework.org/schema/security 
                        http://www.springframework.org/schema/security/spring-security.xsd">
</beans:beans>

搭建简单登录&注销demo

配置maven

<dependency>
	      <groupId>org.springframework.security</groupId>
	      <artifactId>spring-security-web</artifactId>
	      <version>4.1.0.RELEASE</version>
	    </dependency>
	    <dependency>
	      <groupId>org.springframework.security</groupId>
	      <artifactId>spring-security-config</artifactId>
	      <version>4.1.0.RELEASE</version>
</dependency>

代理Servlet 过滤器

Spring Security借助一系列Servlet过滤器来提供各种安全性功能。我们只需在应用的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>

配置Spring Security

spring-security.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-4.3.xsd
                        http://www.springframework.org/schema/security 
                        http://www.springframework.org/schema/security/spring-security.xsd">
	
	<http auto-config="true" use-expressions="false">
		<intercept-url pattern="/admin**" access="ROLE_ADMIN"/>
		<form-login 
		    login-page="/login"
		    login-processing-url="/j_spring_security_check"
		    default-target-url="/welcome" 
			authentication-failure-url="/login?error" 
			username-parameter="username"
			password-parameter="password" />
		<logout logout-url="/j_spring_security_logout" logout-success-url="/login?logout" />
		<!-- enable csrf protection -->
		<csrf/>
	</http>

	<authentication-manager>
		<authentication-provider>
		  <user-service>
			<user name="user1" password="123456" authorities="ROLE_USER" />
			<user name="admin" password="123456" authorities="ROLE_ADMIN" />
		  </user-service>
		</authentication-provider>
	</authentication-manager>
</beans:beans>

form-login属性详解
form-login是spring security命名空间配置登录相关信息的标签,它包含如下属性:

  • login-page 自定义登录页url,默认为/login
  • login-processing-url 登录请求拦截的url,也就是form表单提交时指定的action
  • default-target-url 默认登录成功后跳转的url
  • always-use-default-target 是否总是使用默认的登录成功后跳转url
  • authentication-failure-url 登录失败后跳转的url
  • username-parameter 用户名的请求字段 默认为userName
  • password-parameter 密码的请求字段 默认为password
  • authentication-success-handler-ref 指向一个AuthenticationSuccessHandler用于处理认证成功的请求,不能和default-target-url还有always-use-default-target同时使用
  • authentication-success-forward-url 用于authentication-failure-handler-ref
  • authentication-failure-handler-ref 指向一个AuthenticationFailureHandler用于处理失败的认证请求
  • authentication-failure-forward-url 用于authentication-failure-handler-ref
  • authentication-details-source-ref 指向一个AuthenticationDetailsSource,在认证过滤器中使用

logout 属性详解
当我们指定了http元素的auto-config属性为true时logout定义是会自动配置的,此时我们默认退出登录的URL为“/j_spring_security_logout”,可以通过logout元素的logout-url属性来改变退出登录的默认地址。

  • invalidate-session 表示是否要在退出登录后让当前session失效,默认为true。
  • delete-cookies 指定退出登录后需要删除的cookie名称,多个cookie之间以逗号分隔。
  • logout-success-url 指定成功退出登录后要重定向的URL。需要注意的是对应的URL应当是不需要登录就可以访问的。
  • success-handler-ref 指定用来处理成功退出登录的LogoutSuccessHandler的引用。

intercept-url 属性详解
指定拦截的url:通过pattern指定当前intercept-url定义应当作用于哪些url。
指定访问权限: 可以通过access属性来指定intercept-url对应URL访问所应当具有的权限。access的值是一个字符串,其可以直接是一个权限的定义,也可以是一个表达式。常用的类型有简单的角色名称定义,多个名称之间用逗号分隔。其中必须要以ROLE_为前缀。

<intercept-url pattern="/admin**" access="ROLE_ADMIN,ROLE_USER"/>

还支持Spring表达式,必须将< http > 的use-expressions设置为true

<intercept-url pattern="/admin**" access="hasRole(ROLE_ADMIN)"/>

在这里插入图片描述
指定访问协议: 如果你的应用同时支持Http和Https访问,且要求某些URL只能通过Https访问,这个需求可以通过指定intercept-url的requires-channel属性来指定。requires-channel支持三个值:http、https和any。any表示http和https都可以访问。

配置控制器

LoginController.java

@Controller
public class LoginController {
	@RequestMapping(value="/login")
	public ModelAndView showHomePage(@RequestParam(value = "error", required = false) String error,
			@RequestParam(value = "logout", required = false) String logout) {
		ModelAndView model = new ModelAndView();
		if (error != null) {
			model.addObject("error", "无效的用户名和密码!");
		}
		if (logout != null) {
			model.addObject("msg", "您已成功注销。");
		}
		model.setViewName("login");
		return model;
	}
	
	@RequestMapping(value="/success")
	public String showSuccessPage() {
		return "success";
	}
	
	@RequestMapping(value="/welcome")
	public String showWelcomePage() {
		return "hello";
	}
	
	@RequestMapping(value="/admin")
	public String showAdminPage() {
		return "admin";
	}
}

前台页面代码

login.jsp

<body>
<div id="login-box">
	<h3>Spring Security 欢迎进入</h3>	
	<c:if test="${not empty error }">
		<div class="error">${error}</div>
	</c:if>
	<c:if test="${not empty msg }">
		<div class="msg">${msg}</div>
	</c:if>
	<form action='<c:url value='/j_spring_security_check' />' method="post">
		<table>
			<tr>
				<td>用户名:</td>
				<td>
					<input type="text" name="username"/>
				</td>
			</tr>
			<tr>
				<td>密码:</td>
				<td>
					<input type="password" name="password"/>
				</td>
			</tr>
			<tr>
				<td colspan="2" align="center">
					<input type="submit" value="登录" />
				</td>
			</tr>
		</table>
			<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
	</form>
</div>
</body>

hello.jsp

<body>
	<h1>欢迎进入 Spring Security</h1>
	<c:url value="/j_spring_security_logout" var="logoutUrl" />
	<form action="${logoutUrl}" method="post" id="logoutForm">
		<input type="hidden" name="${_csrf.parameterName}"
			value="${_csrf.token}" />
	</form>
	<a href="javascript:formSubmit()">注销登录</a>
	<a href="<c:url value="/admin" />">后台管理</a>
</body>

admin.jsp

<body>
	<h1>欢迎进入:后台管理页面</h1>
</body>

保护视图级别的元素

为了支持视图级别的安全性,Spring Security提供了一个JSP标签库。这个标签库很小且只包含3个标签,如下图所示:
在这里插入图片描述
为了使用JSP标签库,需要在对应JSP中声明如下:

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

此外还需要加入以下依赖

<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-taglibs</artifactId>
			<version>4.1.0.RELEASE</version>
			<type>jar</type>
			<scope>compile</scope>
</dependency>

访问认证信息的细节

显示认证用户的用户名

<h1>你好,<security:authentication property="principal.username"/></h1>

在这里插入图片描述

根据权限渲染

< security:authorize>JSP标签能够根据用户授予的权限有条件地渲染页面的部分内容。

<security:authorize access="hasRole('ROLE_ADMIN')"><a>admin 用户才可以看到</a></security:authorize>

<security:authorize url="/admin**"><a>admin 用户才可以看到</a></security:authorize>

注意:在上下文中需要加载如下bean

<beans:bean id="webexpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
	</beans:bean>

认证用户

  • 内存(基于Spring配置)用户存储库
  • 基于JDBC的用户存储库
  • 基于LDAP的用户存储库
  • OpenID分散式的用户身份识别系统
  • 中心认证服务(CAS)
  • X.509证书
  • 基于JAAS的提供者

配置内存用户存储库

在Spring配置中声明用户的详细信息,代码如下:

<user-service>
			<user name="user1" password="123456" authorities="ROLE_USER" />
			<user name="admin" password="123456" authorities="ROLE_ADMIN" />
</user-service>

用户信息声明在< user-service>之中,每个能登录应用程序的用户只有一个< user>元素,属性name和password分别指定了登录名和密码,authorities属性用于设置逗号分隔权限列表——即允许用户做的事情。
用户服务准备好后,剩下的事情就是将其装配到Spring Security的认证管理器中:

<authentication-manager>
		<authentication-provider user-service-ref="userService" />
	</authentication-manager>

基于数据库进行认证

用关系型数据库中存储用户信息:

<!-- 基于数据库进行认证 -->
	<jdbc-user-service id="jdbcUserService" data-source-ref="dataSource"
		users-by-username-query="SELECT username,password,true FROM user WHERE username=?"
		authorities-by-username-query="SELECT username,authority FROM user WHERE username=?"/>
	
	<authentication-manager erase-credentials="false">
		<authentication-provider user-service-ref="jdbcUserService" />
	</authentication-manager>

在这里插入图片描述

基于LDAP的用户存储库

目前用不上这块后续学习更新。。。

启用remember-me功能

< http>
	...
	<remember-me key="spitter" token-validity-seconds="241920"/>
< /http >

保护方法调用

目前用不上这块后续学习更新。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值