保护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目录服务器来配笸认证功能。如果这些可选方案无法满足认证需求的话,我们还学

习了如何创建和配笸自定义的用户服务。

Spring实战第九章学习笔记————保护Web应用的更多相关文章

  1. Spring实战第一章学习笔记

    Spring实战第一章学习笔记 Java开发的简化 为了降低Java开发的复杂性,Spring采取了以下四种策略: 基于POJO的轻量级和最小侵入性编程: 通过依赖注入和面向接口实现松耦合: 基于切面 ...

  2. #Spring实战第二章学习笔记————装配Bean

    Spring实战第二章学习笔记----装配Bean 创建应用对象之间协作关系的行为通常称为装配(wiring).这也是依赖注入(DI)的本质. Spring配置的可选方案 当描述bean如何被装配时, ...

  3. Spring实战第六章学习笔记————渲染Web视图

    Spring实战第六章学习笔记----渲染Web视图 理解视图解析 在之前所编写的控制器方法都没有直接产生浏览器所需的HTML.这些方法只是将一些数据传入到模型中然后再将模型传递给一个用来渲染的视图. ...

  4. Spring实战第八章学习笔记————使用Spring Web Flow

    Spring实战第八章学习笔记----使用Spring Web Flow Spring Web Flow是一个Web框架,它适用于元素按规定流程运行的程序. 其实我们可以使用任何WEB框架写流程化的应 ...

  5. AS开发实战第二章学习笔记——其他

    第二章学习笔记(1.19-1.22)像素Android支持的像素单位主要有px(像素).in(英寸).mm(毫米).pt(磅,1/72英寸).dp(与设备无关的显示单位).dip(就是dp).sp(用 ...

  6. 聊天室或文字直播间的效果(AS开发实战第二章学习笔记)

    聊天室或文字直播间的效果即是新的文字消息总是加入窗口末尾,同时窗口内部的文本整体向上滚动,窗口的大小.位置保持不变聊天室用到的属性与方法说明gravity 指定文本的对齐方式,取值left|botto ...

  7. TextView的跑马灯效果(AS开发实战第二章学习笔记)

    TextView的跑马灯效果跑马灯用到的属性与方法说明singleLine 指定文本是否单行显示ellipsize 指定文本超出范围后的省略方式focusable 指定是否获得焦点,跑马灯效果要求设置 ...

  8. Android Studio图形基础(AS开发实战第二章学习笔记)

    图形基础 一.drawable 在代码中引用drawable文件可分为两种情况 (1)使用setBackgroundResource和setImageResource方法,可直接在参数中指定drawa ...

  9. Spring实战第五章学习笔记————构建Spring Web应用程序

    Spring实战第五章学习笔记----构建Spring Web应用程序 Spring MVC基于模型-视图-控制器(Model-View-Controller)模式实现,它能够构建像Spring框架那 ...

随机推荐

  1. andorid 网络通信最简单demo

    要和后台进行通信 一开始发现接不到数据 后来发生了线程错误 在网上查到:在一些高版本中,与网络通信的操作因为要花费比较大的时间,所以应该放在单独的线程中去做. 但为什么一些网上demo没有放在单独的线 ...

  2. JVM构架、GC垃圾回收机制的理解

     JVM是Java Virtual Machine(Java虚拟机)的缩写 1.程序计数器 它的作用可以看做是当前线程所执行的字节码的行号指示器. 每个线程都有一个程序计算器,就是一个指针,指向方法区 ...

  3. watch、computed、methods的区别

    1. `computed`属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算.主要当作属性来使用,要return出去一个值:2. `methods`方法表示一个具体的操作,主要书写业务逻辑:3. ...

  4. 涉及JSP、Servlet的页面编码问题

    1. JSP页面中,二处的字符编码有何区别 1.<%@ page contentType="text/html;charset=UTF-8" %> 是服务器端java程 ...

  5. 初学oracle遇到些小麻烦

    前段时间学习了Oracle数据库,在超级用户sys下运行一些基本语句的时候都没有发现有什么问题,但是却发现不能执行删除字段的的命令,老师检查说可能是权限不够,但是在授权之后依旧不能完成该语句,所以就另 ...

  6. python脚本批量杀死redis链接

    #!/usr/bin/python #coding:utf8 import sys import commands,time,re ##自定义redis链接类 from redismodel impo ...

  7. ASP.NET HttpHandler加水印

    一.指定Handler方式 1.添加Handler一般处理程序 2.PicHandler.ashx源码如下: 需要的引用: using System; using System.Collections ...

  8. Maven命令参数

    命令参数 备注 mvn -v --version 显示版本信息; mvn -V --show-version 显示版本信息后继续执行Maven其他目标; mvn -h --help 显示帮助信息; m ...

  9. Lavavel5.5源代码 - Pipeline

    <?php class Pipeline { protected $passable; protected $pipes = []; protected $method = 'handle'; ...

  10. 微信小程序缓存

    购物车数据加入缓存,相同的商品值修改数量,然后再次加入缓存中 修改购物车的数据的时候同理,都是修改缓存数据然后加入到缓存中. 具体的使用方法看官方文档,我只是提供思路