建筑物身份管理,包括身份验证和授权? 尝试Stormpath! 我们的REST API和强大的Java SDK支持可以消除您的安全风险,并且可以在几分钟内实现。 注册 ,再也不会建立auth了!
更新 :我们最近发布了对Stormpath Spring Security集成的修订。 您不再需要从特殊的Stormpath安全配置器适配器继承。 而是使用Stormpath DSL(特定于域的语言)。 看下面看这有多容易。
♥在Stormpath,我们♥Spring Boot。 构建丰富的Java Web应用程序变得如此轻松有趣。
我们对最新的Java SDK版本感到非常兴奋,其中包括对我们的Spring Security和Spring Boot支持的重大改进。
如果您以前曾经构建过Web应用程序,那么您将知道所有“用户资料”都是您的头疼。 Stormpath为开发人员提供了开箱即用的所有“用户资料”,因此您可以继续真正关心的是您的应用程序! 到本教程完成时(我保证不到15分钟),您将拥有一个可以正常运行的Spring Boot Web应用程序,该应用程序可以通过Spring Security保护用户对受限路径的访问,并得到Stormpath的支持。
我们将专注于我们的Spring Boot集成,以推出一个简单的Spring Boot Web应用程序,该应用程序具有完整的用户注册和登录系统,并具有以下功能:
- 登录和注册页面
- 密码重置工作流程
- 根据组成员身份限制访问
- 能够轻松启用Java库中的其他Stormpath功能(API身份验证,SSO,社交登录等)的功能
在本演示中,我们将使用stormpath-default-spring-boot-starter 。 它的模块化设计在Spring Boot 1.3.0和Spring Security 4.0.3以及Spring Boot WebMVC和Thymeleaf模板引擎中得到了体现。 我将使用Mac,终端应用程序和IntelliJ IDE。
本教程的所有代码都可以在这里找到。
在整个文章中,您可以通过单击Deploy to Heroku按钮来查看示例代码。 您需要做的就是注册一个免费的Heroku帐户。
什么是暴风雨?
Stormpath是一项API服务,允许开发人员创建,编辑和安全地存储
用户帐户和用户帐户数据,并将它们与一个或多个应用程序连接。 我们的API使您能够:
- 验证和授权用户
- 存储有关您的用户的数据
- 执行密码和基于社交的登录
- 发送密码重置消息
- 发行基于API的Web应用程序的API密钥
- 以及更多! 查看我们的产品文档
简而言之:我们使用户帐户管理变得更加轻松,安全和更多
可扩展性比您可能习惯的高。
准备开始了吗? 在此处注册免费的开发者帐户。
启动您的Spring Boot项目
有您的Stormpath开发者帐户? 大! 让我们开始吧…
无论你是一个Maven 的Maven或摇篮克里特 ,让您的项目设置是一个单元。
这是一个以pom.xml
开头的文件:
<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/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.stormpath.sample</groupId><artifactId>stormpath-spring-boot-spring-security-tutorial</artifactId><version>0.1.0</version><name>Spring Boot Spring Security Stormpath Tutorial</name><description>A simple Spring Boot Web MVC application with Spring Security and out-of-the-box login and self-service screens!</description><dependencies><dependency><groupId>com.stormpath.spring</groupId><artifactId>stormpath-default-spring-boot-starter</artifactId><version>1.0.RC6</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>1.3.0.RELEASE</version><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build></project>
而且,这是一个以以下内容开头的build.gradle
文件:
buildscript {repositories {mavenCentral()}dependencies {classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.0.RELEASE")}
}apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'spring-boot'group = 'com.stormpath'
version = '0.1.0'repositories {mavenCentral()
}dependencies {compile group: 'com.stormpath.spring', name: 'stormpath-default-spring-boot-starter', version:'1.0.RC6'
}
您可能会注意到,对于Maven和Gradle来说,都存在一个依赖关系: stormpath-default-spring-boot-starter
。 对。 而已。 正如您将在下面看到的那样,一个依赖项立即为您提供了所有的Spring Boot,Spring Security和Stormpath魔术。
收集您的API凭证和应用程序参考
应用程序和Stormpath之间的连接通过“ API密钥对”进行保护。 您将提供这些密钥
到您的Web应用程序,并且在与Stormpath通信时将使用它们。 您可以从管理控制台下载API密钥对。 登录后,您可以从主页下载API密钥对,它将下载apiKey.properties
文件-我们稍后将使用它。
在管理控制台中时,您要获取默认Stormpath应用程序的href。 在Stormpath中,Application对象用于将Web应用程序链接到Stormpath中的用户存储。 所有新的开发人员帐户都有一个名为“我的应用程序”的应用程序。 在管理控制台中单击“应用程序”,然后单击“我的应用程序”。 在该页面上,您将看到应用程序的Href。 复制它-我们稍后将需要它。
编写Spring Boot应用程序
该部分的代码可以在代码库的LockedDown标记中找到。
我们需要三个小的Java类和一个html模板来启动Webapp的第一个版本。 它们足够小,我会把它们放在这里。 让我们开始吧!
Spring Boot应用程序入口点
所有的Spring Boot应用程序都有一个入口点,其作用与普通的Java程序相同。 它具有main
方法和所有内容。
这是Application.java
:
@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}
6行代码(包括@SpringBootApplication
批注)拉开了序幕。
Spring安全配置
默认情况下(以及最佳安全实践),Spring Security会锁定整个应用程序。 它将其锁定到甚至无法访问的地步! 尽管这符合最佳安全性实践,但并不是很有用。 另外,我们需要将Spring Security和Stormpath挂钩。 这将我们带到我们的SpringSecurityWebAppConfig.java
:
@Configuration
public class SpringSecurityWebAppConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.apply(stormpath());}
}
@Configuration
注释使Spring Boot将该类实例化为配置。 .apply(stormpath())
将所有Stormpath优点(身份验证和授权工作流程)挂接到Spring Security中。
因为configure
方法中没有进一步的配置,所以我们仍然会看到将所有内容锁定的默认行为。 但是,我们将看到默认的Stormpath流程,而不是默认的Spring Security身份验证流程。 也就是说,尝试浏览到应用程序中的任何路径将导致重定向到Stormpath login
页面。
因此,一个1行的方法调用就可以保证安全!
Spring WebMVC紧密联系在一起
我们上面的安全性配置可确保保护应用程序中的所有路径。
控制器确定请求的路径如何定向以显示哪些模板。
这是我们的HelloController.java
:
@Controller
public class HelloController {@RequestMapping("/")String home() {return "home";}
}
@Controller
注释@Controller
Spring Boot这是一个控制器。 我们在第3行/
上定义了一个路径。 第5行返回Thymeleaf模板,命名为home
。
7行代码,我们有模型-视图-控制器(MVC)路由。
带我们
默认情况下,Thymeleaf模板引擎将在类路径中名为templates
的文件夹中查找从控制器返回的templates
。 它还将寻找.html
的默认扩展名。
因此,当上述控制器返回"home"
,Thymeleaf将在resources/templates/home.html
找到模板。
让我们看一下home.html
文件:
<html xmlns:th="http://www.thymeleaf.org"><head><!--/*/ <th:block th:include="fragments/head :: head"/> /*/--></head><body><div class="container-fluid"><div class="row"><div class="box col-md-6 col-md-offset-3"><div class="stormpath-header"><img src="http://stormpath.com/images/template/logo-nav.png"/></div><h1 th:inline="text">Hello, [[${account.fullName}]]!</h1><a th:href="@{/logout}" class="btn btn-danger">Logout</a></div></div></div></body>
</html>
第1行为Thymeleaf设置了th
名称空间。
第3行看起来像html / xml注释。 但是,这是Thymeleaf接受的指令,以在此模板中包含片段。 该片段位于: resources/templates/fragments/head.html
。 该片段包含所有要挂接到Bootstrap样式中的视图的设置。
第13和14行是操作所在的位置。 由于应用程序中的每条路径均已锁定,因此我们知道进入此页面的唯一方法是登录后。Stormpath的神奇之处在于,一旦登录, account
对象就始终在您的视图范围内。 第13行显示已登录用户的全名。 第14行提供了单击后注销的链接。
有关使用Thymeleaf模板的更多信息,请单击此处 。
让我们火起来!
创建一个Stormpath帐户,15行Java代码和19行HTML模板代码(其中3行非常重要),使我们到达了受Spring Security保护并受Stormpath支持的功能齐全的Spring Boot WebMVC应用程序的地步。
如果您以前将apiKey.properties
文件存储在标准位置: ~/.stormpath/apiKey.properties
并且只有为您创建的默认Stormpath应用程序,则无需其他配置即可启动该应用程序。
这是Maven的方式:
mvn clean package
mvn spring-boot:run
注意:由于存在repackage
执行, spring-boot-maven-plugin
还会创建一个uber-jar。 您可以通过运行java来行使相同的代码:
mvn clean package
java -jar target/*.jar
这是Gradle的方式:
gradle clean build
java -jar build/libs/*.jar
真? 是吗 对!
您可以浏览到http:// localhost:8080 /并查看其运行情况。
如果您将apiKey.properties
文件存储在其他位置,或者定义了其他Stormpath应用程序怎么办? 没问题!
还记得您之前保存的Application Href吗? 我们现在将使用它。
这是Maven的方式:
mvn clean package
STORMPATH_API_KEY_FILE=~/.stormpath/apiKey.properties \
STORMPATH_APPLICATION_HREF=https://api.stormpath.com/v1/applications/4YHCurbtcaFC4TKKsd3AYQ \
mvn spring-boot:run
这是Gradle的方式:
gradle clean build
STORMPATH_API_KEY_FILE=~/.stormpath/apiKey.properties \
STORMPATH_APPLICATION_HREF=https://api.stormpath.com/v1/applications/4YHCurbtcaFC4TKKsd3AYQ \
java -jar build/libs/*.jar
通过将STORMPATH_API_KEY_FILE
和STORMPATH_APPLICATION_HREF
环境变量添加到命令行,我们可以轻松地告诉我们的应用程序在哪里可以找到api键以及要使用哪个Stormpath应用程序。
Stormpath Java SDK具有极其灵活的配置机制。 当我们开始限制Stormpath Group成员对您的应用程序的访问时,我们将在下面看到更多内容。
使用Spring Security完善的访问控制
该部分的代码可以在代码库的BasicAccessControl标记中找到。
在上一节中,我们创建了一个紧密锁定的应用程序。 每个路径(包括/
)都要求您首先登录。
也许您想要一个可公开访问的主页。 也许您希望网站的某些部分可以被任何经过身份验证的用户访问,而站点的另一部分则只能包含属于特定组的成员。
我们将在本节中探索那些细粒度的控件。
我们将从允许公众访问主页开始。 用户仍然必须进行身份验证才能访问任何其他页面。
Spring安全:门口的保镖
还记得以前的空SpringSecurityWebAppConfig.java
吗? 我们现在将添加一些东西:
@Configuration
public class SpringSecurityWebAppConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.apply(stormpath()).and().authorizeRequests().antMatchers("/").permitAll();}
}
Spring Security提供了一个流畅的界面来提供访问规则。
在上面的5-8行中,我们正在建立一个规则集,该规则集关于Spring Security如何允许访问我们的应用程序。
您可以用简单的英语来表示:
Permit anyone to go to the front door
Ensure that they've authenticated for anything else
我们指定的规则优先于锁定所有内容的默认行为。
让我们也更新我们的home.html
模板:
<html xmlns:th="http://www.thymeleaf.org"><head><!--/*/ <th:block th:include="fragments/head :: head"/> /*/--></head><body><div class="container-fluid"><div class="row"><div class="box col-md-6 col-md-offset-3"><div class="stormpath-header"><img src="http://stormpath.com/images/template/logo-nav.png"/></div><!--/* displayed if account IS NOT null, indicating that the user IS logged in */--><div th:if="${account}"><h1 th:inline="text">Hello, [[${account.fullName}]]!</h1><a href="/restricted" class="btn btn-primary">Restricted</a><a th:href="@{/logout}" class="btn btn-danger">Logout</a></div><!--/* displayed if account IS null, indicating that the user IS NOT logged in */--><div th:unless="${account}"><h1>Who are you?</h1><a href="/restricted" class="btn btn-primary">Restricted</a></div></div></div></div></body>
</html>
请注意,我们现在有两个不同的部分。 第一个从第13行开始,如果用户已登录,则显示第一个。
如果用户未登录,则显示从第20行开始的第二部分。
这是正在运行的Thymeleaf模板。 它提供了非常强大的控件,可有条件地显示模板的各个部分。
在进行任何其他更改之前,让我们在这里暂停并像以前一样启动应用程序。
当浏览到http:// localhost:8080时 ,您将看到home
模板的未经身份验证的版本。
单击“ Restricted
按钮,您将按预期重定向到login
表单。 验证之后,您将进入404
页面,因为我们尚未定义受限页面。
让我们对其进行设置以完成本节。
定义受限页面就像在我们的控制器中添加路线并创建要显示的模板一样容易。 这是更新的HelloController.java
:
@Controller
public class HelloController {@RequestMapping("/")String home() {return "home";}@RequestMapping("/restricted")String restricted() {return "restricted";}
}
并且,这是一个新的restricted.html
模板:
<html xmlns:th="http://www.thymeleaf.org"><head><!--/*/ <th:block th:include="fragments/head :: head"/> /*/--></head><body><div class="container-fluid"><div class="row"><div class="box col-md-6 col-md-offset-3"><div class="stormpath-header"><img src="http://stormpath.com/images/template/logo-nav.png"/></div><h1 th:inline="text">[[${account.fullName}]], You are allowed here.</h1><a href="/" class="btn btn-primary">Go Home</a></div></div></div></body>
</html>
注意我们如何重新使用head
片段为该模板提供Bootstrap样式。
再次重新启动该应用程序,您将获得完整的体验。 记下主页如何更改,具体取决于您是否登录。
通过组成员身份进行Spring Security访问控制
该部分的代码可以在代码存储库的GroupAccessControl标记中找到。
Spring Security提供了一组注释和一种丰富的表达语言,用于控制对应用程序中方法的访问。 @PreAuthorize
是最常用的Spring Security批注。 并且,最常用的SpringEL表达式包括hasRole
。
Stormpath集成了将Stormpath组连接到Spring Security角色的机制。
让我们看一下代码,然后将其分解。 我们将添加一项新服务,以限制组成员身份的访问。 这是AdminService
:
@Service
public class AdminService {@PreAuthorize("hasRole(@roles.ADMIN)")public boolean ensureAdmin() {return true;}
}
上面的第3行是关键。 注释和SpringEL表达式可以用简单的英语表示为:
Before this method is even entered,
check to see that user is authenticated and
is a member of the ADMIN group
check to see that user is authenticated
的check to see that user is authenticated
可能并不明显。 发生的是, @PreAuthorize
检查只能在经过身份验证的用户上执行。 Spring Security非常聪明,可以在检查用户是否是指定组的成员之前检查用户是否已登录。
让我们深入探讨上面的Spring Expression Language。 Spring Security在哪里寻找@roles.ADMIN
? @
符号是特殊的–它标识Java Bean。 在这种情况下,一个名为roles
的bean。 我们希望在该bean内定义一个名为ADMIN
的常量。
最终, hasRole
需要检查代表Stormpath Group的唯一Href。 因此,我们的ADMIN
常数必须是一个Java String
,该String
将Href保留到用于管理员的Stormpath组中。
为了完成此配置并使它具有Roles.java
动态性,我们需要一个名为Roles.java
的新类:
@Component
public class Roles {public final String ADMIN;@Autowiredpublic Roles(Environment env) {ADMIN = env.getProperty("stormpath.authorized.group.admin");}
}
这9条线是如此强大,我在这里一览无余! 让我们深入。
通过在第1行用@Component
注释此类,Spring将实例化它并将其公开为bean。 猜猜豆子的名字是什么? Spring将采用该类的名称,并以驼峰式大小写以默认情况下派生Bean名称。 因此,bean的名称是roles
。 甜!
第5行的@Autowired
注释使Spring Environment
对象传递到构造函数中。 在构造函数内部,由于ADMIN
已被声明为final
,因此我们唯一的机会是对其进行设置-要求能够在hasRoles
子句中使用它。
难题的最后一部分利用了一些Stormpath配置魔术。 请注意,我们正在将ADMIN
的值设置为名为stormpath.authorized.group.admin
的环境属性。 这是标准的Spring。 如果您的application.properties
文件中有一个具有该名称的属性,那么它将在Spring Environment中可用。
Stormpath增加了将其设置为系统环境变量的能力,从而无需在应用程序中的任何位置硬编码该值(在这种情况下为Stormpath Group Href)。
通常,系统环境变量全部为大写字母,单词之间用下划线分隔。 Stormpath Java SDK自动将这些系统变量转换为小写的点分表示法。
挖这个:
STORMPATH_AUTHORIZED_GROUP_ADMIN=https://api.stormpath.com/v1/groups/1wcsYMUZhzytUH5GmdaFXC \
java -jar build/libs/spring-boot-spring-security-tutorial-0.1.0.jar
在后台,Stormpath会将STORMPATH_AUTHORIZED_GROUP_ADMIN
系统环境变量转换为stormpath.authorized.group.admin
环境变量。 这将被我们上面的代码处理。
! 谁想到只需几行代码就能实现这种魔力!
现在,我们需要将AdminService
到我们的控制器。 这是我们更新的HelloController.java
的相关部分:
@Controller
public class HelloController {@AutowiredAdminService adminService;...@RequestMapping("/admin")String admin() {adminService.ensureAdmin();return "admin";}
}
在第4行和第5行自动连接AdminService
。请注意,在第11行,我们正在调用adminService.ensureAdmin
方法。 如果已登录的用户ADMIN
组中,则将生成403
(禁止)响应。
最后的代码整理工作是创建一个admin.html
模板。 在与该帖子相关的代码中,有一个简单的admin.html
模板,该模板显示了格式正确的消息,确认您确实是管理员。
现在,要查看实际效果,您需要在管理控制台中进行一些Stormpath内务处理。
步骤如下:
- 创建一个新的应用程序
- 为应用程序创建一个名为“ admin”的新组
- 在管理组中创建一个新帐户
- 不在管理员组中创建一个新帐户
在与此帖子相关的代码中,我还包括了一个方便的错误页面,因此,如果您不在admin组中,那么您将获得格式正确的页面,而不是默认的403
页面。
让我们来看看它的作用。 我们将像以前一样启动该应用程序,只是这一次我们将对在上一步中创建的新应用程序和组使用在管理控制台中找到的Href。
这是Maven的方式:
mvn clean package
STORMPATH_API_KEY_FILE=~/.stormpath/apiKey.properties \
STORMPATH_APPLICATION_HREF=https://api.stormpath.com/v1/applications/4YHCurbtcaFC4TKKsd3AYQ \
STORMPATH_AUTHORIZED_GROUP_ADMIN=https://api.stormpath.com/v1/groups/1wcsYMUZhzytUH5GmdaFXC \
mvn spring-boot:run
这是Gradle的方式:
gradle clean build
STORMPATH_API_KEY_FILE=~/.stormpath/apiKey.properties \
STORMPATH_APPLICATION_HREF=https://api.stormpath.com/v1/applications/4YHCurbtcaFC4TKKsd3AYQ \
STORMPATH_AUTHORIZED_GROUP_ADMIN=https://api.stormpath.com/v1/groups/1wcsYMUZhzytUH5GmdaFXC \
java -jar build/libs/spring-boot-spring-security-tutorial-0.1.0.jar
浏览到/admin
页面。
如果您以在Stormpath admin
组(在我的情况下为micah+admin@stormpath.com)中创建的用户身份登录,则可以访问管理页面。 如果您以创建的用户身份登录,而该用户不在Stormpath admin
组中(在我的情况下为micah+user@stormpath.com),则将显示禁止页面。
无论您以谁身份登录,都可以像我们之前设置的那样访问/restricted
页面。
包起来
好吧,我们在这里涵盖了很多领域,不是吗!
我们看到了如何保护单个页面以及如何基于组中的成员资格来保护方法。
我们看到了如何在你的类,它扩展应用 Stormpath WebSecurityConfigurerAdapter
定义不同的路径访问控制,以及利用Spring安全的@PreAuthorize
注释控制的更细的晶粒。
我们看到了Stormpath Java SDK管理环境配置属性以为您的应用程序提供高度灵活性而无需进行任何硬编码的几乎神奇的方式。
Java SDK和Spring Boot集成中还有许多功能。 在此处查看深入的教程。
随时随地提供支持或亲自给我 。
建筑物身份管理,包括身份验证和授权? 尝试Stormpath! 我们的REST API和强大的Java SDK支持可以消除您的安全风险,并且可以在几分钟内实现。 注册 ,再也不会建立auth了!
翻译自: https://www.javacodegeeks.com/2016/06/simple-web-app-spring-boot-spring-security-stormpath-15-minutes.html