现在的位置: 首页 > 综合 > 正文

登录以保护应用

2018年08月08日 ⁄ 综合 ⁄ 共 2636字 ⁄ 字号 评论关闭
 

本小节实现登录功能。在本小节,读者还将学习到 Filter 的用法和 uitls 的用法。

首先创建用于登录的 Domain Class,在控制台输入:

grails create-domain-class Users

然后修改 Domain Class 的内容如下:

class Users { 
String username
String password
static constraints = {
username(size:5..60,blank:false,unique:true)
password(size:5..60,blank:false)
}
}

相信读者一定不希望将密码的名文直接保存到数据库中。这里就涉及一个 SHA 的加密过程,Grails 希望我们在 utils 中实现这个过程。在 grails-app/utils 中创建一个名为 PasswordCodec 的 Groovy 类(强调一下类名必需是 XXXCodec),编写代码如下:

import java.security.MessageDigest
import sun.misc.BASE64Encoder
import sun.misc.CharacterEncoder

class PasswordCodec {
static encode = { str ->
MessageDigest md = MessageDigest.getInstance('SHA')
md.update(str.getBytes('UTF-8'))
return (new BASE64Encoder()).encode(md.digest())
}
}

接下来我们写程序让应用启动时自动往 Users 表添加一条记录。BootStrap 类可以帮助我们实现这个功能,修改 grails-app/config/BootStrap.groovy 的代码:

class BootStrap {
def init = { servletContext ->
def user = new Users(id:1,username:'liangshixing'
,password:'liangshixing')
user.password = user.password.encodeAsPassword()
user.save()
}
def destroy = { }
}

BootStrap 类中的 init 闭包中的代码将在启动时首先执行。这里我们创建了一个 Users 对象,并为它初始化了用户名和密码。

这里要注意一点,user.password.encodeAsPassword() 正是源于我们创建的 Utils 类,Grails 会根据命名约定,查找并执行 PasswordCodec 类的 encode 闭包,从而实现了 SHA 的加密。

Utils 类也是 Grails 的约定编码的一个典泛。

接下来实现表单页面和 Controller(可以先使用 generate-all,然后在自动生成的代码上改),这里仅摘录 Controller 的代码:

class UsersController {
def index = { redirect(action:login,params:params) }
def login = {
def users = new Users()
users.properties = params
return ['users':users]
}
def loginCheck = {
def users = new Users(params)
if(!users.hasErrors()) {
users.password = params.password.encodeAsPassword()
def resultUsers=Users.findByUsernameAndPassword(users.username,users.password)
if(resultUsers) {
session.user = resultUsers
redirect(controller:'member',action:'search')
} else {
flash.message = 'Login failed: incorrect username and password'
render(view:'login',model:[users:users])
}
} else {
render(view:'login',model:[users:users])
}
}
def logOut = {
session.invalidate()
redirect(controller:'users',action:'login')
}
}

login Action 会跳转到 login.gsp,用于显示登录的表单页面。

loginCheckAction 将检查用户名密码是否正确。如果正确,则将 Users 对象保存到 session 中,然后重定向到搜索 member 的页面;如果不正确,报错并要求重新登录。

logOut 调用 session 的 invalidate 方法,可以清空 session。然后调用 redirect 从定向到登录页面。

登录登出的功能已经实现了,但我们的应用还没有被保护起来,Filter 可以帮助实现这个功能(Grails1.0rc1 中第一次支持这个功能)。

首先在 grails-app/config/ 文件夹中创建一个名为 LoginFilters 的类(类名必须以 Filters 结尾)。编写如下代码:

class LoginFilters {
def filters = {
loginCheck(controller:'*', action:'*') {
before = {
if(!session.user) {
if(!actionName.equals('login')
&& !actionName.equals('logOut')
&& !actionName.equals('loginCheck')
&& !actionName.equals('list')
&& !actionName.equals('search')
&& !actionName.equals('show')) {
redirect(controller:'users',action:'login')
return false
}
}
}
}
}
}

Filters 类中可以使用 actionNamecontrollerName 去获取 action 和 controller 的名称。本文例子中的限制只有 login,logOut,loginCheck,list,search,show 不需要登录,如果访问其它页面,都需要登录。

抱歉!评论已关闭.