项目以springboot,springsecurity等技术为后端,vue+elementUI为前端。
需求,增加密码的修改。
打开修改密码dialog对话框,原密码中要输入并验证是否正确,新密码和确认新密码是验证是否一致和正则匹配,然后修改按钮提交到后端进行数据库中user表的密码更新。
一、后端部分
1、原密码的校验:
a.控制器
@PostMapping("/selectByUserNameAndPassword")
@ResponseBody
public Result<Boolean> selectByUserNameAndPassword(@RequestBody Map<String,String> map){
if (map.get("username") == null || map.get("password") == null) {
return Result.failure(501,"非法参数usernameORpassword");
} else {
return userService.selectByUserNameAndPassword(map.get("username"),map.get("password"));
}
}
b.业务逻辑
由于密码加密后,每次重新加密得出的字符串是不一样的,因此不能单纯地靠字符串去做对比,使用BCryptPasswordEncoder对象提供的的matches方法。
@Override
public Result<Boolean> selectByUserNameAndPassword(String username, String password) {
//密码对比判断使用matches方法判断
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
//查出用户
User user = userDao.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername, username));
if (user == null) {
return Result.defaultSuccess(false);
}
//重点方法:密码比较
boolean matches = encoder.matches(password, user.getPassword());
return Result.defaultSuccess(matches);
}
2、密码的更新
a.控制器
@PostMapping("/updataPassword")
@ResponseBody
public Result<Boolean> updataPassword(@RequestBody Map<String,String> map){
if (map.get("username") == null || map.get("passwordOld") == null || map.get("passwordNew") == null) {
return Result.failure(501,"非法参数");
} else {
return userService.updataPassword(map.get("username"),map.get("passwordOld"),map.get("passwordNew"));
}
}
b.业务逻辑
@Override
public Result<Boolean> updataPassword(String username, String passwordOld, String passwordNew) {
//需要再次验证旧密码
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
//查出用户
User user = userDao.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername, username));
if (user == null) {
return Result.defaultSuccess(false);
} else {
//密码比较
boolean matches = encoder.matches(passwordOld, user.getPassword());
//旧密码通过校验后才会进行更新密码操作
if (matches){
user.setPassword(new BCryptPasswordEncoder().encode(passwordNew));
userDao.updateById(user);
return Result.defaultSuccess(true);
} else {
return Result.defaultSuccess(false);
}
}
}
二、前端部分
1、dialog对话框
<!--密码修改框-->
<el-dialog title="修改密码" :visible="showPassword" :close-on-click-modal="false" width="20%" @close="updataPasswordCancle('password')">
<!--rules绑定验证规则-->
<el-form :model="password" class="demo-ruleForm" status-icon :rules="rules" ref="password">
<!--prop为要验证的字段-->
<el-form-item label="原密码" :label-width="formLabelWidth" :required="true" prop="old">
<el-input v-model.trim="password.old" maxlength="20" show-word-limit placeholder="必填" show-password autofocus></el-input>
</el-form-item>
<el-form-item label="新密码" :label-width="formLabelWidth" :required="true" prop="new">
<el-input v-model.trim="password.new" maxlength="20" show-word-limit placeholder="必填" show-password></el-input>
</el-form-item>
<el-form-item label="确认新密码" :label-width="formLabelWidth" :required="true" prop="newOk">
<el-input v-model.trim="password.newOk" maxlength="20" show-word-limit placeholder="必填" show-password></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="updataPasswordCancle('password')">取 消</el-button>
<el-button type="primary" @click="updataPasswordOk('password')" >修 改</el-button>
</div>
</el-dialog>
2、js代码逻辑
<script>
// import store from '../store/index.js'
import Vue from 'vue'
import store from './store/index.js'
export default {
data () {
// 验证原密码是否正确
let checkOld = (rule, value, callback) => {
var _this = this
if (!value) {
return callback(new Error('旧密码不能为空'))
} else {
this.$axios.post('user/selectByUserNameAndPassword', {'username': _this.username, 'password': _this.password.old}).then(function (res) {
if (res.data.data === false) {
return callback(new Error('密码错误'))
} else {
callback()
}
})
}
}
// 新密码以字母开头,8-12位长度
let checkNew = (rule, value, callback) => {
if (!value) {
return callback(new Error('新密码不能为空'))
} else {
// 8-12位,以字母开头
let match = /^[a-zA-Z]\w{7,11}$/
if (!match.test(value)) {
return callback(new Error('新密码以字母开头,8-12位长度'))
} else {
callback()
}
}
}
// 验证确认密码
let checkNewOk = (rule, value, callback) => {
if (!value) {
return callback(new Error('新密码不能为空'))
} else {
if (value !== this.password.new) {
return callback(new Error('新密码必须一致'))
} else {
// 8-12位,以字母开头
let match = /^[a-zA-Z]\w{7,11}$/
if (!match.test(value)) {
return callback(new Error('新密码以字母开头,8-12位长度'))
} else {
callback()
}
}
}
}
return {
formLabelWidth: '100px',
username: '',
showPassword: false,
password: {},
rules: {
old: [
{required: true, validator: checkOld, trigger: 'blur'}
],
new: [
{required: true, validator: checkNew, trigger: 'blur'}
],
newOk: [
{required: true, validator: checkNewOk, trigger: 'blur'}
]
}
}
},
created () {
var token = JSON.parse(this.$store.state.token)
// 获取用户名
this.username = token.username
},
methods: {
// 开启修改密码dialog
updataPassword () {
this.password = {}
this.showPassword = true
},
// 取消,隐藏,清空password,清除验证
updataPasswordCancle (formName) {
this.showPassword = false
this.password = {}
this.$refs[formName].resetFields()
},
updataPasswordOk (formName) {
var _this = this
this.$refs[formName].validate((valid) => {
// 验证通过
if (valid) {
this.$axios.post('user/updataPassword', {'username': _this.username, 'passwordOld': _this.password.old, 'passwordNew': _this.password.new}).then(function (res) {
if (res.data.data === true) {
_this.$message({
type: 'success',
message: '修改密码成功!'
})
_this.showPassword = false
_this.password = {}
}
})
} else {
// 没有通过验证
return false
}
})
}
}
}
</script>
三、security中取消普通用户对用户密码修改的拦截
http.authorizeRequests() //所有请求拦截
// 密码验证及修改密码只需用户认证
.antMatchers("/user/selectByUserNameAndPassword", "/user/updataPassword").authenticated()