八、【spring】web应用安全设计

内容

  • Spring Security
  • 使用Servlet规范中的Filter保护Web应用
  • 基于数据库和LDAP进行认证

关键词

8.1 理解Spring Security模块

Spring Security:是为基于Spring的应用程序提供声明式安全保护的安全性框架。Spring Security提供了完整的安全性解决方案,它能够在Web请求级别和方法调用级别处理身份认证和授权。因为基于Spring框架,所以Spring Security充分利用了依赖注入(DI)和面向切面的技术。

通过两种角度解决安全问题

  1. 使用Servlet规范中的Filter保护Web请求并限制URL级别的访问。
  2. 使用Spring AOP保护方法调用——借助于对象代理和使用通知,能够确保只有具备适当权限的用户才能访问安全保护的方法。

8.1.1 理解模块

Security被分成以下11个模块

模块 描述
ACL 支持通过访问控制列表(access control list,ACL)为域对象提供安全性
切面(Aspects) 一个很小的模块,当使用Spring Security注解时,会使用基于AspectJ的切面,而不是使用标准的Spring AOP
CAS客户端(CAS Client) 提供与Jasig的中心认证服务(Central Authentication Service,CAS)进行集成的功能
配置(Configuration) 包含通过XML和Java配置Spring Security的功能支持
核心(Core) 提供Spring Security基本库
加密(Cryptography) 提供了加密和密码编码功能
LDAP 支持基于LDAP进行认证
OpenID 支持使用OpenID进行集中式认证
Remoting 提供了对Spring Remoting的支持
标签库(Tag Library) Spring Security的JSP标签库
Web 提供了Spring Security基于Filter的Web安全性支持

应用程序的类路径下至少要包含Core和Configuration两个模块

9.1.2 简单的安全配置

Spring Security借助Spring Filter来提高各种安全性功能
Spring Security配置

package test
import .......Configuration;
import .......EnableWebSecurity;
import .......WebSecurityConfigureAdapter;

@Configuration
// 启用Web安全性
@EnableWebSecurity
// 启用Web MVC安全性
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigureAdapter {

}

以上只是写了一个类扩展了WebSecurityConfigureAdapter类,但是要是启用还需要重载WebSecurityConfigureAdapter的三个方法。

方法 描述
configure(WebSecurity) 通过重载,配置Spring Security的Filter链
configure(HttpSecurity) 通过重载,配置如何通过拦截器保护请求
configure(AuthenticationManageBuilder) 通过重载,配置user_detail服务

虽然重载了以上的方法,但是问题依然存在,我们需要

  • 配置用户存储
  • 指定那些请求需要认证,哪些不需要,以及提供什么样的权限
  • 提供一个自定义的登陆页面,替代原来简单的默认登录页

8.2 选择查询用户详细信息的服务

Spring Security提供了基于数据存储来认证用户,它内置了多种常见的用户存储场景,如内存,关系型数据库以及LDAP,也可以编写并插入自定义的用户存储实现。

8.2.1 使用基于内存的用户存储

扩展了WebSecurityConfigureAdapter,所以重载Configure方法,并以AuthenticationManageBuilder作为传入参数

package test.config

import org.springframework.context.annotation.Configuration;
import org.springframework.beans.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
  	protected void configure(AuthenticationManageBuilder auth) throws Exception {
		auth.inMemoryAuthentication().withUser("user").password("password").roles("USER").and().withUser("admin").password("password").roles(""USER","ADMIN");
	}
}

代码解析:

  • configure()方法中使用类使用构造者风格的接口来构建认证配置。
  • 调用withUser()方法为内存用户存储添加新的用户,该方法的UserDetailsManagerConfigurer.UserDetailsBuilder,
  • 添加两个用户,user具有USER角色,admin具有USER和ADMIN角色。
  • roles方法是authorities方法的简写形式。

配置用户详细信息的方法

方法 描述
accountExpired(boolean) 定义账号是否过期
accountLocked(boolean) 定义账号是否已经锁定
and() 用来连接配置
authorities(GrantedAuthority) 授予某个用户一项或多项权限
authorities(List<? extends grantedAuthority>) 授予某个用户一项或多项权限
authorities(string ….) 授予某个用户一项或多项权限
credentialsExpired(boolean) 定义凭证是否已经过期
disabled(boolean) 定义账号是否被禁用
password(String) 用户定义的密码
roles(String …) 授予某个用户一项或多项角色

8.3 拦截请求

请求不是不拦截,也不是都拦截,而是需要适度的拦截

@Override
protected void configure(HttpSecurity http) throws Exception {
	http.authorizeRequests().antMatchers("/spitters/me").authenticated().antMatchers(HttpMethod.POST,"/spittles").authenticated().anyRequest().permitAll();
}

保护路径配置方法列表

方法 描述
access(String) 如果给定的SpEL表达式计算结果为True,就允许访问
anonymous() 允许匿名用户访问
authenticated() 允许认证过的用户访问
denyAll() 无条件拒绝所有访问
fullyAuthenticated() 如果用户是完整认证的话,就允许访问
hasIpAddress(String) 如果请求来自给定IP,允许
hasRole(String) 如果用户具备给定角色的话,就允许
not() 对其他访问求反
permitAll() 无条件允许访问
rememberMe() 如果用户是通过Remember-me功能认证的,允许

8.3.1 强制通道安全性

使用requireChannel()方法,借助这个方法可以为各种URL模式声明所请求的通道

```java
@Override
protected void configure(HttpSecurity http) throws Exception {
	http.authorizeRequests().antMatchers("/spitters/me").authenticated().antMatchers(HttpMethod.POST,"/spittles").authenticated().anyRequest().permitAll().and().requiresChannel().antMatchers("/spitters/form").requireSecure();<--需要HTTPS
	.requiresInsecure().antMatchers("/").requireInSecure();<--使用HTTP
}

8.3.2 防止跨站请求伪造

跨站请求伪造(cross-site request forgery,CSRF)

Spring Security通过一个同步token的方式来实现CSRF防护的功能。它将会拦截状态变化的请求(非GET、HEAD等的请求)并检查CSRF_token。如果请求中不包含CSRF token或者与服务器的token不符合则会失败,并抛出csrfException异常。意味着在所有表单中必须在一个”_csrf”的域中提交token

<form method="POST" th:action="@{/spittle}">
...
</form>

当然也可以在代码中取消该功能
.csrf.disable();即可

Tags: