Grails 基本身份验证
了解如何使用“基本”HTTP 身份验证方案保护 Grails 应用程序。
作者:Sergio del Amo
Grails 版本 5.0.1
1 入门
RFC7617 定义了“基本”超文本传输协议 (HTTP) 身份验证方案,该方案使用 Base64 编码以用户 ID/密码对的形式传输凭据。
在本指南中,你将创建一个 Grails 应用程序并通过 HTTP 基本身份验证将其保护起来。
1.1 你将需要什么
若要完成本指南,你需要以下内容
-
一些你的时间
-
一个好用的文本编辑器或 IDE
-
安装了 JDK 1.8 或更高版本,并正确配置了
JAVA_HOME
1.2 如何完成指南
若要开始,请执行以下操作
-
下载并解压源代码
或
-
克隆 Git 仓库
git clone https://github.com/grails-guides/grails-basicauth.git
Grails 指南仓库包含两个文件夹
-
initial
初始项目。通常是一个带有额外代码的简单 Grails 应用程序,让你有一个起点。 -
complete
一个完整的示例。它是完成指南介绍的步骤并对initial
文件夹应用这些更改的结果。
若要完成本指南,请转到 initial
文件夹
-
cd
到grails-guides/grails-basicauth/initial
并按照下一部分中的说明进行操作。
如果你 cd 到 grails-guides/grails-basicauth/complete ,你可以直接到已完成示例 |
如果你想从头开始,请使用 Grails 应用程序 Forge 创建一个新的 Grails 应用程序。
2 编写应用程序
使用 rest-api
配置文件创建应用程序
grails create-app example --profile=rest-api
2.1 添加安全依赖项
我们需要做的第一件事是将 spring-security-core
Grails 插件添加到 build.gradle
中。
compile 'org.grails.plugins:spring-security-core:4.0.0.RC2'
然后,运行命令
grails s2-quickstart example.grails User Role
该命令将生成以下域类
-
grails-app/domain/example.grails.User
-
grails-app/domain/example.grails.Role
-
grails-app/domain/example.grails.UserRole
一个密码编码器监听器
src/main/groovy/example.grails.UserPasswordEncoderListener
以及在以下位置的默认安全配置
-
grails-app/conf/application.groovy
修改生成的 application.groovy
以启用基本身份验证。
grails.plugin.springsecurity.useBasicAuth = true
2.2控制器
创建返回经过身份验证的用户的用户名的 `HomeController`。
package example.grails
import groovy.transform.CompileStatic
import grails.plugin.springsecurity.SpringSecurityService
import grails.plugin.springsecurity.annotation.Secured
import grails.plugin.springsecurity.userdetails.GrailsUser
@CompileStatic
@Secured('isAuthenticated()')
class HomeController {
static responseFormats = ['json']
SpringSecurityService springSecurityService
def index() {
[name: loggedUsername()]
}
String loggedUsername() {
if ( springSecurityService.principal == null ) {
return null
}
if ( springSecurityService.principal instanceof String ) {
return springSecurityService.principal
}
if ( springSecurityService.principal instanceof GrailsUser ) {
return ((GrailsUser) springSecurityService.principal).username
}
null
}
}
2.3 视图
借助 JSON 视图将控制器输出呈现为 JSON Payload。
model {
String name
}
json {
username name
}
2.4 GORM 数据服务
GORM 数据服务通过使用 GORM 逻辑自动实现抽象类或接口的能力,免除了实施服务层逻辑的工作。
创建一个 GORM 数据服务以简化 User
域类的 CRUD 操作。
package example.grails
import grails.gorm.services.Service
@Service(User)
interface UserDataService {
User save(String username, String password, boolean enabled, boolean accountExpired, boolean accountLocked, boolean passwordExpired)
void delete(Serializable id)
int count()
}
2.5 测试
创建一个通过基本身份验证验证用户身份验证流程的测试。
package example.grails
import grails.testing.mixin.integration.Integration
import grails.testing.spock.OnceBefore
import io.micronaut.http.HttpRequest
import io.micronaut.http.HttpResponse
import io.micronaut.http.HttpStatus
import io.micronaut.http.client.HttpClient
import spock.lang.Specification
@Integration
class HomeControllerSpec extends Specification {
UserDataService userDataService
HttpClient client
@OnceBefore
void init() {
String baseUrl = "http://localhost:$serverPort"
this.client = HttpClient.create(baseUrl.toURL())
}
def "verify basic auth is possible"() {
given:
final String username = 'sherlock'
final String password = 'elementary'
when:
User user = userDataService.save(username, password, true, false, false, false, )
then:
userDataService.count() == old(userDataService.count()) + 1
when:
HttpRequest request = HttpRequest.GET("/home")
.basicAuth(username, password)
HttpResponse<Map> rsp = client.toBlocking().exchange(request, Map)
then:
rsp.status == HttpStatus.OK
and:
rsp.body().username == username
cleanup:
userDataService?.delete(user?.id)
}
}
要运行测试,请执行 ./gradlew test
2.6 后续步骤
阅读 Grails Springs Security Core 插件文档的 基本和摘要身份验证 部分,了解基本身份验证的可用不同配置选项。