实现忘记密码功能,以及完善部分单元测试

This commit is contained in:
F嘉阳
2018-02-25 21:32:27 +08:00
parent a7b8b30186
commit 3e75e1753f
9 changed files with 360 additions and 26 deletions

View File

@@ -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);
}
}
} }

View 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;
}

View File

@@ -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;

View File

@@ -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);//返回更新的行数
} }

View File

@@ -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);
}

View File

@@ -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,62 +29,69 @@ public class UserService {
@Autowired @Autowired
private TbUserqueRepository userqueRepository; private TbUserqueRepository userqueRepository;
@Autowired
private VUserqueRepository vUserqueRepository;
@Autowired @Autowired
private VUserinfoRepository vUserinfoRepository; private VUserinfoRepository vUserinfoRepository;
public TbUser doLoginService(String name,String password){ public TbUser doLoginService(String name, String password) {
//TbUser user = (TbUser)tbUserRepository.findByColname(name).get(); //TbUser user = (TbUser)tbUserRepository.findByColname(name).get();
Optional<TbUser> tbUser = tbUserRepository.findByColname(name); Optional<TbUser> tbUser = tbUserRepository.findByColname(name);
TbUser user = new TbUser(); TbUser user = new TbUser();
if (tbUser.isPresent()){ if (tbUser.isPresent()) {
user = (TbUser)tbUser.get(); user = (TbUser) tbUser.get();
}else { } else {
throw new UserException(ResultEnum.EMPTY_DATA); throw new UserException(ResultEnum.EMPTY_DATA);
} }
if (user!=null){ if (user != null) {
if (password.equals(user.getColpassword())){ if (password.equals(user.getColpassword())) {
return user; return user;
}else { } else {
throw new UserException(ResultEnum.WRONGPASS); throw new UserException(ResultEnum.WRONGPASS);
} }
}else { } else {
throw new UserException(ResultEnum.USER_NOTEXIST); throw new UserException(ResultEnum.USER_NOTEXIST);
} }
} }
public boolean doRegisterService(TbUser tbUser){ public boolean doRegisterService(TbUser tbUser) {
TbUser user = tbUserRepository.save(tbUser); TbUser user = tbUserRepository.save(tbUser);
if (user!=null){ if (user != null) {
//throw new UserException(ResultEnum.SUCCESS); //throw new UserException(ResultEnum.SUCCESS);
return true; return true;
} }
return false; return false;
} }
public List<TbUser> findAllUser(){ public List<TbUser> findAllUser() {
return tbUserRepository.findAll(); return tbUserRepository.findAll();
} }
public VUserinfo findUserInfo(Integer coluserid){ public VUserinfo findUserInfo(Integer coluserid) {
return vUserinfoRepository.findById(coluserid).get(); return vUserinfoRepository.findById(coluserid).get();
} }
public Optional<TbUser> findByColname(String name){ public Optional<TbUser> findByColname(String name) {
return tbUserRepository.findByColname(name); return tbUserRepository.findByColname(name);
} }
public boolean addUserQue(TbUserque userque){ public boolean addUserQue(TbUserque userque) {
TbUserque tbUserque = userqueRepository.save(userque); TbUserque tbUserque = userqueRepository.save(userque);
if (tbUserque!=null) if (tbUserque != null)
return true; return true;
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;
}
} }

View File

@@ -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;
} }
}); });

View File

@@ -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>

View File

@@ -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"));
}
} }