文章目录
应用安全属于安全防护体系中的重要一环,但也是最薄弱的一环,究其原因,或许是:
- 应用核心职责是完成业务和产品的功能需求,而安全确实非功能性需求,在资源有限的情况下,企业一定是更加注重将有限的资源投入到“开疆扩土”上去,否则,穷家破瓦的,也真没什么值得安全防护的。
- 大部分应用开发者对应用安全知之甚少,而且安全一般属于一个企业或者业界秘而不宣的信息,所以,在没有一个专职安全团队负责推动整个安全防护体系落实的情况下,零零散散和线上落实的一些应用安全防护已经算是很不错的了。
- “树大招风”,树不大的时候,那些“风”通常也不会来找你麻烦,所以,大部分中小企业,除非应用了一些业界广泛使用的软件或者方案被连贯性的伤害到,大部分情况下,这些中小企业并不知道这类潜在风险,或者是他们自身不会为黑客们(cracker)带来太大的利用价值
好在我们这些Java开发者生活在Spring框架营造的生态圈之中,所以,关于应用安全这种头疼的问题,Spring生态圈里也有现成的解决方案,即从Acegi发展起来的SpringSecurity。但说实话,SpringSecurity在整个社区中的名声并不好,尤其在开发者眼中,“复杂(Too Compliated),太重(Too Heavyweight)”,但实际上,如果大家真的扑进去了解一个人,哦,不对一个框架,就会发现,其实SpringSecurity框架本身的设计还是挺优秀的,SpringSecurity可以任意裁剪,而且还提供了丰富的开箱即用的安全特性支持。这里其实存在一个常见的设计取舍,我们到底应该为了良好的扩展和组合型而将组件拆分的精细一些,还是应该为了使用便利,适度忽略定制化的需求,提供一个功能简化的一站式方案?不管SpringSecurity团队当时是如何选择的,既然已经成为了事实,给使用这的感受不好,那么,我们就要想办法改善这种现状,spring-boot-starter-scecurity就是一种答案。
spring-boot-starter-security主要面向Web应用安全,配合spring-boot-starter-web,要使用SpringBoot构建一个安全的对外提供服务的Web应用简直太容易了:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven- 4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.keevol.unveilspring.chapter3</groupId>
<artifactId>web- security- demo</artifactId>
<version>0.0.1- SNAPSHOT</version>
<packaging>jar</packaging>
<name>web- security- demo</name>
<description>web security demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF- 8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <!-- 其他 依赖-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
在当前项目中只要添加需要的Controller实现,一个添加了基本安全防护的Web应用就诞生了。spring-boot-starter-security默认会提供一个基于HTTP Basic认证的安全防护策略,默认用户名为user,访问密码则在当前Web应用启动的时候,打印到控制台,类似于:
2016- 01- 01 13: 57: 00. 596 INFO 17966 --- [ost- startStop- 1] b. a. s. Au- thenticationManagerConfiguration :
Using default security password: 560ff91b- 0ae7- 492c- ad16- 603e1adec54c
如果我们希望对HTTP Basic认证的用户名密码进行定制,可以通过如下配置项进行:
security.user.name={ 个人 希望 设置 的 用 户名}
security.user.password={ 个人 希望 使用 的 访问 密码}
除此之外,spring-boot-starter-security还会默认启用一些必要的Web安全防护,比如针对XSS、CSRF等常见针对Web应用的攻击,同时,也会将一些常见的静态资源路径排除在安全防护之外。
但是,说实话,spring-boot-starter-security提供的默认安全策略相对于生产环境来说,还是太弱了,但也没办法,既要安全,又要便利,spring-boot-starter-security默认情况下已经尽量做到够好了。不过好在SpringSecurity扩展性不错,要在其上构建一套真正严谨有效的Web应用安全防护体系也并非难事,只不过,需要我们先能够从其架构设计上理解并把握它,然后再在SpringSecurity和SpringBoot的基础上构建一套符合自身需要的Web应用安全方案。
了解SpringSecurity基本设计
SpringSecurity框架不但囊括了基本的认证和授权功能,而且还提供了加密解密、统一登录等一系列相关支持。我们下面只对基本的认证和授权的设计简单介绍下
我们可以将Spring Security的几个核心概念按照下图勾勒在一起
- 访问者(Accessor)需要访问某个资源(Resources)是这个场景中最原始的需求,但并不是谁都可以访问资源,也不是任何资源都允许任何人访问,所以,中间我们需要加入一些检查和防护。
- 在访问资源的所经路径上,可能需要上山、过桥、下海行船,不管怎么样,这些所经之路对于我们要防护的资源来说都是比较好的设置关卡点,对应上图就是FilterInvoation(对应Web应用场景)、MethodInvocation以及Joinpoint,这些在Spring Security框架中统称为Secured Object(s)
- 我们知道了在哪里设置关卡最合适,下一步就是设置关卡,对应不同的所经之路,我们分别设置类似FilterSecurityInterceptor、MethodSecurityInterceptor以及AspectJSecurityInterceptor这样的关卡来负责拦截非法资源访问的闯入者们;而在Spring Security框架的设计中,关卡的概念统一抽象成AbstractSecurityInterceptor,而FilterSecurityInterceptor、MethodSecurityInterceptor以及AspectJSecurityInterceptor都是它的具体实现类
- 好啦,把门到是有了,可是他们不知道该拦谁,不该拦谁,所以,我们需要有类似神盾局(S.H.I.E.L.D)这样的机构,由这个机构决定谁可以放行,谁必须阻截,而在SpringSecurity框架中AccessDecisionManager就是这个控制机构,AccessDecisionManager将决定谁可以访问那些资源
- 现在剩下最后一个问题,这个谁怎么定义?我们总得知道当前这个访问者是谁才能告知AccessDecisionManager阻截还是放行,所以,SpringSecurity框架中AuthenticationManager将解决的是访问者身份认证的问题,只有确定你在册了,才可以给你授权访问(除非我们运行匿名访问某些公共资源)
AuthenticationManager、AccessDecisionManager和AbstractSecurityIntrerceptor属于SpringSecurity框架的基础铁三角,AuthenticationManager、AccessDecisionManager负责定制规则,AbstractSecurityIntrerceptor负责执行。所有基于不同场景的应用方案,基本上都是在这个基础核心的基础上衍生出来的,比如,Web安全。