保护Web应用
在这一章我们将使用切面技术来探索保护应用程序的方式。不过我们不必自己开发这些切面————我们将使用Spring Security,一种基于Spring AOP和Servlet规范的Filter实现的安全框架。
Spring Security简介
Spring Security是为基于Spring的应用程序提供声明式安全保护的安全性框架。它能够在Web请求级别和方法调用级别处理身份认证和授权。充分利用了依赖注入和面向切面技术。
理解Spring security的模块
模块 | 描述 |
---|---|
ACL | 支持通过访问控制列表(ACL)为域对象提供安全性 |
切面 | 使用基于AspectJ的切面,而不是使用标准的SpringAOP |
CAS客户端 | 提供与Jasig的中心认证服务(CAS)进行集成的功能 |
配置(Configuration) | 包含通过XML和java配置Spring Security的功能支持 |
核心(Core) | 提供Spring Security基本库 |
加密 | 提供了加密和密码编码的功能 |
LDAP | 支持基于LDAP进行认证 |
OpenID | 支持使用OpenID进行集中式认证 |
Remoting | 提供了对Spring Remoting的支持 |
标签库 | Spring Security的JSP标签库 |
Web | 提供了Spring Security基于Filter的Web安全性支持 |
应用程序的类路径下至少要含有Core和Configuration这两个模块。
过滤Web请求
Spring security借助一系列Servlet Filter来提供各种安全性功能。DelegatingFilterProxy是一个特殊的Servlet Filter,它会将工作委托给一个javax.servlet.Filter实现类,这个实现类作为一个<bean>注册在Spring应用的上下文。如图所示:
aaarticlea/png;base64,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" alt="image">
xml实现:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DeleagatingFilterProxy
</filter-class>
</filter>
在这里,我们把<filter-name>设置成了springSecurityFilterChain。这是因为我们马上将Springsecurity配置在Web安全性中,。DelegatingFilterProxy会把过滤逻辑委托给名为springSecurityFilterChain的Filter bean。
Java配置:
import *;
public class SecurityWebInitializer extends AbstractSecurityWebApplicationInitializer{}
编写简单的安全性配置
启用Web安全性功能的最简单配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
}
@EnableWebSecurity注解将会启用Web安全功能。但它本身并没有什么用处。Springsecurity必须配置在一个实现了WebSecurityConfigurer的bean中或者扩展WebSecurityConfigurerAdapter。最为简单的方法还是刚刚的程序最为简单。
为SpringMVC启用Web安全性能的最简单配置
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
}
@EnableWebMvcSecurity注解还配置了一个Spring Mvc参数解析解析器,这样的话处理器方法就能够通过带有@AuthenticationPrincipal租借的参数获得认证用户的principal。
而以上的两个配置会将应用严格锁定,导致没有人能进入该系统了。这是我们要通过重载WebSecurityConfigurerAdapter的三个configure方法来配置Web安全性。
方法 | 描述 |
---|---|
configure(WebSecurity) | 通过重载,配置Spring Security的Filter链 |
configure(HttpSecurity) | 通过重载,配置如何通过拦截器保护请求 |
configure(AuthenticationManagerBuilder) | 通过重载,配置user-detail服务 |
为了让Springsecurity满足我们应用的需求,还需要再添加一点配置。具体来讲我们需要:
- 配置用户存储;
- 指定哪些请求需要认证,哪些不需要,以及所需要的权限;
- 指定一个自定义的登录页面,替代原先默认的登录页。
选择查询用户详细信息的服务
使用基于内存的用户存储
因为我们的安全配置是扩展了WebSecurityConfigurerAdapter,因此配置用户存储的最简单方式就是重载configure()方法,并以AuthenticationManagerBuilder作为传入参数。通过inMemoryAuthentication()方法,我们可以启用配置并任意填充基于内存的用户存储。
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER","ADMIN");
}
}
方法 | 描述 |
---|---|
accountExpired(boolean) | 定义账号是否已经过期 |
accountLocked(boolean) | 定义账号是否已经锁定 |
and() | 用来连接配置 |
authorities(GrantedAuthority...) | 授予用户一项或多项权限 |
authorities(List<? extends GrantedAuthority>) | 授予用户一项或多项权限 |
authorities(String...) | 授予用户一项或多项权限 |
credentialExpired(boolean) | 定义凭证是否已经过期。 |
disabled(boolean) | 定义账号是否已被禁用 |
password(boolean) | 定义用户的密码 |
roles(String) | 授予用户一项或多项角色 |
基于数据库列表进行认证
为了配置SpringSecurity使用以JDBC为支撑的用户存储,我们可以使用jdbcAuthentication
()方法,所需的最少配置:
@Autowired
DataSource datasource;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth
.jdbcAuthentication()
.dataSource(dataSource)
}
重写默认的用户查询功能
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth
.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery(
"select username,password,true "+
"from Spitter where username=?")
.authortiesByUsernameQuery(
"select username,'ROLE_USER' from Spitter where username=?"
);
)
}
将默认的SQL查询替换为自定义的设计时,很重要得一点是要遵循查询的基本协议。所有的查询都以用户名为唯一的参数。认证查询会选取用户名、密码以及启用状态信息.
使用转码后的密码借助passwordEncoder()方法制定一个密码转码器
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth
.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery(
"select username,password,true "+
"from Spitter where username=?")
.authortiesByUsernameQuery(
"select username,'ROLE_USER' from Spitter where username=?")
.passwordEncoder(new StandardPasswordEncoder("53cr3t"));
}
配置自定义的用户服务
当我们需要认证的用户存储在非关系型数据库中,我们需要提供一个自定义的UserDetailsService接口实现。
public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
我们需要做的就是实现loadUserByUsername()方法
public class SpitterUserService implements UserDetailsService{
private final SpitterRepository spitterRepository;
public SpitterUserService(SpitterRepository spitterRepository){
this.spitterRepository = spitterRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{
Spitter spitter = spitterRepository.findByUsername(username);
if(spitter !=null){
List<GrantedAuthority> authorities =
new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("ROLE_SPITTER"));
return new User(
spitter.getUsername(),
spitter.getPassword(),
authorities);
throw new UsernameNotFoundException(
"User '" + username + "' not found."
);
}
}
}
为了使用SpitterUserService来认证用户,我们可以通过userDetailsService()方法将其设置到安全配置中:
@Autowired
SpitterRepository spitterRepository;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth
.userDetailsService(new SpitterUserService(spitterRepository));
}
拦截请求
在应用中不睡所有的请求都需要同等程度的保护,而对每个请求进行安全性控制的关键在于重载configure(HttpSecurity)方法。如下示例:
@Override
protected void configure(HttpSecurity http) throws Exception{
http
.authorizeRequests()
.antMatchers("/spitters/me").authenticated()
.antMatchers(HttpMethod.POST,"/spittles").authenticated()
.anyRequest().permitAll();
}
antMatchers()方法用来指定路径。
下表例举了用来定义如何保护路径的配置方法
方法 | 能够做什么 |
---|---|
access(String) | 如果给定的SpEL表达式计算结果为true,就允许访问 |
anonymous() | 允许匿名用户访问 |
anthenticated() | 允许认证过的用户访问 |
denyAll() | 无条件拒绝所有访问 |
fullyAuthenticated() | 如果用户是完整认证的,就允许访问 |
hasAnyAuthority(String…) | 如果用户具备给定权限中某一个的话,就允许访问 |
hasAnyRole(String…) | 如果用户具备给定角色中某一个的话,就允许访问 |
hasAuthority(String) | 如果用户具备给定权限的话,就允许访问 |
hasIpAddress(String) | 如果请求来自指定IP地址,就允许访问 |
hasRole(String) | 如果用户具备给定角色的话,就允许访问 |
not() | 对其他访问方法的结果求反 |
permitAll() | 无条件允许访问 |
rememberMe(String) | 如果用户是通过Remember-me功能认证的,就允许访问 |
使用Spring表达式进行安全保护
Spring Security支持的所有SpEI表达式
安全表达式 | 计算结果 |
---|---|
hasRole([role]) | 当前用户是否拥有指定角色。 |
hasAnyRole([role1,role2]) | 多个角色是一个以逗号进行分隔的字符串。如果当前用户拥有指定角色中的任意一个则返回true。 |
hasAuthority([auth]) | 等同于hasRole |
hasAnyAuthority([auth1,auth2]) | 等同于hasAnyRole |
Principle | 代表当前用户的principle对象 |
authentication | 直接从SecurityContext获取的当前Authentication对象 |
permitAll | 总是返回true,表示允许所有的 |
denyAll | 总是返回false,表示拒绝所有的 |
isAnonymous() | 当前用户是否是一个匿名用户 |
isRememberMe() | 表示当前用户是否是通过Remember-Me自动登录的 |
isAuthenticated() | 表示当前用户是否已经登录认证成功了。 |
isFullyAuthenticated() | 如果当前用户既不是一个匿名用户,同时又不是通过Remember-Me自动登录的,则返回true。 |
强制通道的安全性
使用HTTP提交数据是—件具有风险的事情。如果使用HTTP发送无关紧要的信息,这可能不是什么大问题。但是如果你通过HTTP发送诸如密码和信用卡号这样的敏感信息的话,那你就是在找麻烦了。通过HTTP发送的数据没有经过加密,黑客就有机会拦截请求并且能够看到他
们想看的数据。这就是为什么敏感信息要通过HTTPS来加密发送的原因。
传递到configure()方法中的HttpSecurity对象,除了具有authorizeRequests()方法以外,还有一个requiresChannel()方法,借助这个方法能够为各种URL模式声明所要求的通道。
@Override
protected void configure(HttpSecurity http) throws Exception{
http
.authorizeRequest()
.antMatchers("/spitters/me").authenticated()
.antMatchers(HttpMethod.POST,"/spittles").authenticated()
.anyRequest().permitAll()
.and()
.requiresChannel()
.antMatchers("/spitter/form").requiresSecure();//需要HTTPS
}
防止跨站请求伪造
跨站请求伪造(cross-site request forgery,CSRF)的—个简单样例。简单来讲,如果—个站
点欺骗用户提交请求到其他服务器的话,就会发生跨站请求伪造(cross-site request forgery,CSRF)攻击,这可能会带来消极的后果。
Spring Security通过—个同步token的方式来实现CSRF防护的功能。它将会拦截状态变化的请求(例如,非GET、HEAD、OPTIONS和TRACE的请求)并检查CSRF
token。如果请求中不包含CSRF token的话,或者token不能与服务器端的token相匹配,请求将会失败,并抛出
CsrfException异常。这意味着在你的应用中,所有的表单必须在—个" csrf"域中提交token,而且这个token必须
要与服务器端计算并存储的token—致,这样的话当表单提交的时候,才能进行匹配。
Spring Security巳经简化了将token放到请求的属性中这—任务。如果使用JSP作为页面模板的话:
<input type="hidden"
name="${_csrf.parameterName}"
value="${_csrf.token}"/>
禁用SpringSecurity的CSRF防护功能:
@Override
protected void configure(HttpSecurity http) throws Exception{
http
```
.csrf()
.disabled();
}
认证用户
启用HTTP BASIC认证
HTTP Basic认证(HTTP Basic Authentication)会直接通过HTTP请求本身,对要访问应用程序的用户进行认证。你可能在以前见过HTTP
Basic认证。当在Web浏览器中使用时,它将向用户弹出—个简单的模态对话框。
但这只是Web浏览器的显示方式。本质上,这是—个HTTP 401响应,表明必须要在请求中包含
—个用户名和密码。在REST客户端向它使用的服务进行认证的场景中,这种方式比较适合。
如果要启用HTTP Basic认证的话,只需在configure()方法所传入的HttpSecurity对象上调用httpBasic()即可。另外,还可以通过调用realmName()方法指定域。如下是在 Spring Security中启用HTTP Basic认证的典型配置:
@Override
protected void configure(HttpSecurity http) throws Exception{
http
.formLogin()
.loginPage("/login")
.and()
.httpBasic()
.realmName("Spittr")
.and()
```
}
启用Remember-me功能
站在用户的角度来讲,如果应用程序不用每次都提示他们登录是更好的。这就是为什么许多站点提供了Remember-me功能,你只要登录过一次,应用就会记住你,当再次回到应用的时候你就不需要登录了。
@Override
protected void configure(HttpSecurity http) throws Exception{
http
.formLogin()
.loginPage("/login")
.and()
.rememberMe()
.tokenvaliditySeconds(2419200)
.key("spitterkey")
```
}
在这里,我们通过—点特殊的配笸就可以启用Remember-me功能。默认情况下,这个功能是通
过在cookie中存储—个token完成的,这个token最多两周内有效。但是,在这里,我们指定这个
token最多四周内有效(2,419,200秒)。
保护视图
略
小结
对于许多应用而言,安全性都是非常重要的切面。Spring Security提供了—种简单、灵活且强大
的机制来保护我们的应用程序。
借助于—系列Servlet Filter,Spring Security能够控制对Web资源的访问,包括Spring MVC控制器。借助于Spring
Security的Java配笸模型,我们不必直接处理Filter,能够非常简沽地声明Web安全性功能。
当认证用户时,Spring Security提供了多种选项。我们探讨了如何基于内存用户库、关系型数据
库和LDAP目录服务器来配笸认证功能。如果这些可选方案无法满足认证需求的话,我们还学
习了如何创建和配笸自定义的用户服务。