实现忘记密码功能,以及完善部分单元测试
This commit is contained in:
@@ -16,6 +16,7 @@ import javax.annotation.Resource;
|
|||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import static com.fjy.spring.constant.GlobalConstant.USER_SESSION_KEY;
|
import static com.fjy.spring.constant.GlobalConstant.USER_SESSION_KEY;
|
||||||
|
|
||||||
@@ -133,9 +134,42 @@ public class DataController {
|
|||||||
return userService.addUserQue(userque);
|
return userService.addUserQue(userque);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*@GetMapping("/finduserque")
|
/**
|
||||||
public TbUserque findUserQue(){
|
* 判断密保问题是否正确,正确返回true,错误返回false,其余反馈异常对象
|
||||||
TbUserque userque = userService;
|
* @param name
|
||||||
|
* @param question
|
||||||
}*/
|
* @param answer
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@GetMapping("/finduserque")
|
||||||
|
public boolean findUserQue(@RequestParam(value = "name")String name
|
||||||
|
,@RequestParam(value = "question")String question
|
||||||
|
,@RequestParam(value = "answer")String answer)throws Exception{
|
||||||
|
Optional<VUserque> userque = userService.findUserQueByName(name);
|
||||||
|
if (!userque.isPresent()){
|
||||||
|
throw new UserException(ResultEnum.EMPTY_QUESTION);
|
||||||
|
}else if(question.equals(userque.get().getQuestion())){
|
||||||
|
if(new BigInteger(CodingUtil.encryptSHA(answer.getBytes())).toString(32).equals(userque.get().getAnswer()))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}else{
|
||||||
|
throw new UserException(ResultEnum.QUESTION_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/resetPass")
|
||||||
|
public boolean resetPass(@RequestParam(value = "name") String name
|
||||||
|
, @RequestParam(value = "password") String password,
|
||||||
|
@RequestParam(value = "question") String question
|
||||||
|
, @RequestParam(value = "answer") String answer) throws Exception {
|
||||||
|
log.info("name:{}, password:{}, question:{}, answer:{}",name,password,question,answer);
|
||||||
|
if (findUserQue(name,question,answer)){
|
||||||
|
//service方法内含有对密码加密的操作
|
||||||
|
return userService.updateColpasswordByColname(password,name);
|
||||||
|
}else {
|
||||||
|
throw new UserException(ResultEnum.ILLEGAL_ACCESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
30
src/main/java/com/fjy/spring/domain/VUserque.java
Normal file
30
src/main/java/com/fjy/spring/domain/VUserque.java
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package com.fjy.spring.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.hibernate.annotations.Immutable;
|
||||||
|
import org.hibernate.annotations.Subselect;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Data
|
||||||
|
@Immutable
|
||||||
|
@Subselect("SELECT * FROM v_userque")
|
||||||
|
public class VUserque {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(name = "coluserid")
|
||||||
|
private Integer userid;
|
||||||
|
|
||||||
|
@Column(name = "colquestion")
|
||||||
|
private String question;
|
||||||
|
|
||||||
|
@Column(name = "colanswer")
|
||||||
|
private String answer;
|
||||||
|
|
||||||
|
@Column(name = "colname")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -12,6 +12,9 @@ public enum ResultEnum {
|
|||||||
WRONG_FORM(607,"表单错误"),
|
WRONG_FORM(607,"表单错误"),
|
||||||
EMPTY_DATA(608,"无数据"),
|
EMPTY_DATA(608,"无数据"),
|
||||||
ID_NULLPOINT(609,"id为空"),
|
ID_NULLPOINT(609,"id为空"),
|
||||||
|
EMPTY_QUESTION(610,"该用户未设置密保问题"),
|
||||||
|
QUESTION_ERROR(611,"问题与答案不匹配"),
|
||||||
|
|
||||||
;
|
;
|
||||||
private Integer code;
|
private Integer code;
|
||||||
private String msg;
|
private String msg;
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package com.fjy.spring.repository;
|
|||||||
|
|
||||||
import com.fjy.spring.domain.TbUser;
|
import com.fjy.spring.domain.TbUser;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -9,4 +11,7 @@ public interface TbUserRepository extends JpaRepository<TbUser,Integer> {
|
|||||||
|
|
||||||
public Optional<TbUser> findByColname(String name);
|
public Optional<TbUser> findByColname(String name);
|
||||||
|
|
||||||
|
@Modifying
|
||||||
|
@Query("UPDATE TbUser u SET u.colpassword=?1 WHERE u.colname = ?2")
|
||||||
|
public int updateColpasswordByColname(String password,String name);//返回更新的行数
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.fjy.spring.repository;
|
||||||
|
|
||||||
|
import com.fjy.spring.domain.VUserque;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
|
||||||
|
public interface VUserqueRepository extends JpaRepository<VUserque,Integer> {
|
||||||
|
|
||||||
|
public Optional<VUserque> findByName(String name);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,14 +3,19 @@ package com.fjy.spring.service;
|
|||||||
import com.fjy.spring.domain.TbUser;
|
import com.fjy.spring.domain.TbUser;
|
||||||
import com.fjy.spring.domain.TbUserque;
|
import com.fjy.spring.domain.TbUserque;
|
||||||
import com.fjy.spring.domain.VUserinfo;
|
import com.fjy.spring.domain.VUserinfo;
|
||||||
|
import com.fjy.spring.domain.VUserque;
|
||||||
import com.fjy.spring.enums.ResultEnum;
|
import com.fjy.spring.enums.ResultEnum;
|
||||||
import com.fjy.spring.exception.UserException;
|
import com.fjy.spring.exception.UserException;
|
||||||
import com.fjy.spring.repository.TbUserRepository;
|
import com.fjy.spring.repository.TbUserRepository;
|
||||||
import com.fjy.spring.repository.TbUserqueRepository;
|
import com.fjy.spring.repository.TbUserqueRepository;
|
||||||
import com.fjy.spring.repository.VUserinfoRepository;
|
import com.fjy.spring.repository.VUserinfoRepository;
|
||||||
|
import com.fjy.spring.repository.VUserqueRepository;
|
||||||
|
import com.fjy.spring.untils.CodingUtil;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -24,6 +29,9 @@ public class UserService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private TbUserqueRepository userqueRepository;
|
private TbUserqueRepository userqueRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private VUserqueRepository vUserqueRepository;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private VUserinfoRepository vUserinfoRepository;
|
private VUserinfoRepository vUserinfoRepository;
|
||||||
|
|
||||||
@@ -78,8 +86,12 @@ public class UserService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*public TbUserque findUserQue(String question){
|
public Optional<VUserque> findUserQueByName(String name) {
|
||||||
return userqueRepository
|
return vUserqueRepository.findByName(name);
|
||||||
}*/
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public boolean updateColpasswordByColname(String password, String name) throws Exception {
|
||||||
|
return tbUserRepository.updateColpasswordByColname(new BigInteger(CodingUtil.encryptSHA(password.getBytes())).toString(32), name) > 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
let outSideThis = this;
|
||||||
var Main = {
|
var Main = {
|
||||||
data() {
|
data() {
|
||||||
var checkName = (rule, value, callback) => {
|
var checkName = (rule, value, callback) => {
|
||||||
|
let that= this;
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return callback(new Error('用户名不能为空'));
|
return callback(new Error('用户名不能为空'));
|
||||||
}else {
|
}else {
|
||||||
@@ -20,7 +22,42 @@ var Main = {
|
|||||||
})
|
})
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
this.errorNotify(error.message);
|
that.errorNotify(error.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var checkQuestion = (rule, value, callback) => {
|
||||||
|
if (!value) {
|
||||||
|
return callback(new Error('问题不能为空'));
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var checkAnswer = (rule, value, callback) => {
|
||||||
|
let that = this;
|
||||||
|
if (!value) {
|
||||||
|
return callback(new Error('答案不能为空'));
|
||||||
|
} else {
|
||||||
|
axios.get(getRootPath_web() + '/finduserque', {
|
||||||
|
params: {
|
||||||
|
name :outSideThis.findpass.colname.value,
|
||||||
|
question:outSideThis.findpass.question.value,
|
||||||
|
answer: value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(function (response) {
|
||||||
|
console.log(response.data);
|
||||||
|
if (response.data === true) {
|
||||||
|
callback()
|
||||||
|
} else if (response.data === false){
|
||||||
|
return callback(new Error('答案错误'));
|
||||||
|
}else {
|
||||||
|
return callback(new Error(response.data.message));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
console.log(error);
|
||||||
|
that.errorNotify("未知错误");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -99,6 +136,25 @@ var Main = {
|
|||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
var validatePass3 = (rule, value, callback) => {
|
||||||
|
if (value === '') {
|
||||||
|
callback(new Error('请输入密码'));
|
||||||
|
} else {
|
||||||
|
if (this.ruleForm3.checkPass !== '') {
|
||||||
|
this.$refs.ruleForm3.validateField('checkPass');
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var validatePass4 = (rule, value, callback) => {
|
||||||
|
if (value === '') {
|
||||||
|
callback(new Error('请再次输入密码'));
|
||||||
|
} else if (value !== this.ruleForm3.colpassword) {
|
||||||
|
callback(new Error('两次输入密码不一致!'));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
return {
|
return {
|
||||||
ruleForm1: {
|
ruleForm1: {
|
||||||
colname: '',
|
colname: '',
|
||||||
@@ -112,6 +168,30 @@ var Main = {
|
|||||||
colrealname: '',
|
colrealname: '',
|
||||||
colemail: ''
|
colemail: ''
|
||||||
},
|
},
|
||||||
|
ruleForm3: {
|
||||||
|
colname:'',
|
||||||
|
question: '',
|
||||||
|
answer: '',
|
||||||
|
colpassword: '',
|
||||||
|
checkPass: ''
|
||||||
|
},
|
||||||
|
rules3: {
|
||||||
|
colname: [
|
||||||
|
{required: true,validator: checkName1, trigger: 'blur'}
|
||||||
|
],
|
||||||
|
question: [
|
||||||
|
{required: true,validator: checkQuestion, trigger: 'blur'}
|
||||||
|
],
|
||||||
|
answer: [
|
||||||
|
{required: true,validator: checkAnswer, trigger: 'blur'}
|
||||||
|
],
|
||||||
|
colpassword: [
|
||||||
|
{required: true, validator: validatePass3, trigger: 'blur'}
|
||||||
|
],
|
||||||
|
checkPass: [
|
||||||
|
{required: true, validator: validatePass4, trigger: 'blur'}
|
||||||
|
]
|
||||||
|
},
|
||||||
rules1: {
|
rules1: {
|
||||||
colpassword: [
|
colpassword: [
|
||||||
{required: true,validator: validatePass, trigger: 'blur'}
|
{required: true,validator: validatePass, trigger: 'blur'}
|
||||||
@@ -155,12 +235,63 @@ var Main = {
|
|||||||
message: content
|
message: content
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
submitForm(formName) {
|
openNotiSuccess(title, content) {
|
||||||
|
this.$notify({
|
||||||
|
title: title,
|
||||||
|
message: content,
|
||||||
|
type: 'success'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
openNotiError(title, content) {
|
||||||
|
this.$notify.error({
|
||||||
|
title: title,
|
||||||
|
message: content
|
||||||
|
});
|
||||||
|
},
|
||||||
|
submitForm(formName, url) {
|
||||||
this.$refs[formName].validate((valid) => {
|
this.$refs[formName].validate((valid) => {
|
||||||
if (valid) {
|
var that = this;
|
||||||
alert('submit!');
|
if (valid) {//此处暂时去除校验
|
||||||
|
axios({
|
||||||
|
url: getRootPath_web()+'/' + url,
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
name :outSideThis.findpass.colname.value,
|
||||||
|
password:outSideThis.findpass.colpassword.value,
|
||||||
|
question:outSideThis.findpass.question.value,
|
||||||
|
answer:outSideThis.findpass.answer.value,
|
||||||
|
},
|
||||||
|
transformRequest: [function (data) {
|
||||||
|
// Do whatever you want to transform the data
|
||||||
|
let ret = ''
|
||||||
|
for (let it in data) {
|
||||||
|
ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}],
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
|
}
|
||||||
|
}).then(function (response) {
|
||||||
|
console.log(response.data);
|
||||||
|
if (response.data===true){
|
||||||
|
that.openNotiSuccess("成功", "修改成功,请切换至登录选项!");
|
||||||
|
}else if (response.data===false){
|
||||||
|
that.openNotiError("失败", "修改失败!");
|
||||||
|
}else {
|
||||||
|
that.openNotiError("错误", response.data.message);
|
||||||
|
}
|
||||||
|
}).catch(function (error) {
|
||||||
|
console.log(error);
|
||||||
|
that.openNotiError("错误", "服务器错误!");
|
||||||
|
});
|
||||||
|
//console.log(this.$refs.content.value)
|
||||||
|
//this.openNotiSuccess("成功", "修改成功!")
|
||||||
|
//this.$options.methods.openNotiSuccess.bind(this)();
|
||||||
|
//alert('submit!');
|
||||||
} else {
|
} else {
|
||||||
console.log('error submit!!');
|
console.log('error submit!!');
|
||||||
|
that.openNotiError("错误", "表单填写错误!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -92,6 +92,54 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
<el-tab-pane
|
||||||
|
label="找回密码" name="findpass">
|
||||||
|
<el-form
|
||||||
|
:model="ruleForm3" status-icon :rules="rules3" ref="ruleForm3"
|
||||||
|
label-width="100px" class="demo-ruleForm"
|
||||||
|
action="/cms/register/doregister"
|
||||||
|
method="POST" name="findpass">
|
||||||
|
<el-form-item label="用户名"
|
||||||
|
prop="colname">
|
||||||
|
<el-input
|
||||||
|
v-model="ruleForm3.colname" name="colname"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="问题"
|
||||||
|
prop="question">
|
||||||
|
<el-select v-model="ruleForm3.question" placeholder="请选择密保问题" name="question">
|
||||||
|
<el-option label="您母亲的姓名是?" value="您母亲的姓名是?"></el-option>
|
||||||
|
<el-option label="您父亲的姓名是?" value="您父亲的姓名是?"></el-option>
|
||||||
|
<el-option label="您配偶的姓名是?" value="您配偶的姓名是?"></el-option>
|
||||||
|
<el-option label="您的出生地是?" value="您的出生地是?"></el-option>
|
||||||
|
<el-option label="您高中班主任的名字是?" value="您高中班主任的名字是?"></el-option>
|
||||||
|
<el-option label="您初中班主任的名字是?" value="您初中班主任的名字是?"></el-option>
|
||||||
|
<el-option label="您的小学校名是?" value="您的小学校名是?"></el-option>
|
||||||
|
<el-option label="您最熟悉的童年好友名字是?" value="您最熟悉的童年好友名字是?"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="答案"
|
||||||
|
prop="answer">
|
||||||
|
<el-input v-model="ruleForm3.answer"
|
||||||
|
name="answer"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="输入新密码" prop="colpassword">
|
||||||
|
<el-input type="password"
|
||||||
|
v-model="ruleForm3.colpassword" auto-complete="off" name="colpassword"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="确认密码" prop="checkPass">
|
||||||
|
<el-input
|
||||||
|
type="password" v-model="ruleForm3.checkPass"
|
||||||
|
auto-complete="off" name="checkPass"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary"
|
||||||
|
@click="submitForm('ruleForm3','resetPass')">提交
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="resetForm('ruleForm3')">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -33,4 +33,62 @@ public class DataControllerTest {
|
|||||||
.param("answer","YHM"))
|
.param("answer","YHM"))
|
||||||
.andExpect(MockMvcResultMatchers.content().string("true"));
|
.andExpect(MockMvcResultMatchers.content().string("true"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*测试找回密码
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void findUserQue() throws Exception{
|
||||||
|
//测试问题和答案均正确
|
||||||
|
mvc.perform(MockMvcRequestBuilders.get("/finduserque")
|
||||||
|
.param("name","root")
|
||||||
|
.param("question","您配偶的姓名是?")
|
||||||
|
.param("answer","abc"))
|
||||||
|
.andExpect(MockMvcResultMatchers.content().string("true"));
|
||||||
|
|
||||||
|
//测试问题错误
|
||||||
|
mvc.perform(MockMvcRequestBuilders.get("/finduserque")
|
||||||
|
.param("name","root")
|
||||||
|
.param("question","您配偶的姓名是")
|
||||||
|
.param("answer","abc"))
|
||||||
|
.andExpect(MockMvcResultMatchers.content().json("{\n" +
|
||||||
|
" \"code\": 611,\n" +
|
||||||
|
" \"message\": \"问题与答案不匹配\",\n" +
|
||||||
|
" \"data\": null\n" +
|
||||||
|
"}"));
|
||||||
|
|
||||||
|
//测试问题正确,答案错误
|
||||||
|
mvc.perform(MockMvcRequestBuilders.get("/finduserque")
|
||||||
|
.param("name","root")
|
||||||
|
.param("question","您配偶的姓名是?")
|
||||||
|
.param("answer","a"))
|
||||||
|
.andExpect(MockMvcResultMatchers.content().string("false"));
|
||||||
|
|
||||||
|
//未设置问题
|
||||||
|
mvc.perform(MockMvcRequestBuilders.get("/finduserque")
|
||||||
|
.param("name","roo")
|
||||||
|
.param("question","您配偶的姓名是?")
|
||||||
|
.param("answer","a"))
|
||||||
|
.andExpect(MockMvcResultMatchers.content().json("{\n" +
|
||||||
|
" \"code\": 610,\n" +
|
||||||
|
" \"message\": \"该用户未设置密保问题\",\n" +
|
||||||
|
" \"data\": null\n" +
|
||||||
|
"}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试忘记密码操作
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@Transactional
|
||||||
|
public void resetPass() throws Exception{
|
||||||
|
mvc.perform(MockMvcRequestBuilders.post("/resetPass")
|
||||||
|
.param("name","root")
|
||||||
|
.param("question","您配偶的姓名是?")
|
||||||
|
.param("answer","abc")
|
||||||
|
.param("password","admin"))
|
||||||
|
.andExpect(MockMvcResultMatchers.content().string("true"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user