完成隐私设置
This commit is contained in:
parent
fdbd412881
commit
600efd92c3
@ -9,6 +9,7 @@ import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
@ -112,6 +113,10 @@ public class SecurityConfiguration {
|
||||
|
||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException {
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.getWriter().write(JSONObject.toJSONString(RestBean.failure(401, exception.getMessage())));
|
||||
if(exception instanceof BadCredentialsException) {
|
||||
response.getWriter().write(JSONObject.toJSONString(RestBean.failure(403, exception.getMessage())));
|
||||
} else {
|
||||
response.getWriter().write(JSONObject.toJSONString(RestBean.failure(401, exception.getMessage())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,13 +5,18 @@ import com.example.entity.user.AccountInfo;
|
||||
import com.example.entity.user.AccountUser;
|
||||
import com.example.service.UserService;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Validated
|
||||
@RestController
|
||||
@RequestMapping("/api/user")
|
||||
public class UserController {
|
||||
|
||||
private final String EMAIL_REGEX = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$";
|
||||
|
||||
@Resource
|
||||
UserService service;
|
||||
|
||||
@ -36,4 +41,31 @@ public class UserController {
|
||||
public RestBean<AccountInfo> info(@SessionAttribute("account") AccountUser user){
|
||||
return RestBean.success(service.userInfo(user.getId()));
|
||||
}
|
||||
|
||||
@PostMapping("/save-email")
|
||||
public RestBean<String> saveInfo(@Pattern(regexp = EMAIL_REGEX) @RequestParam("email") String email,
|
||||
@SessionAttribute("account") AccountUser user){
|
||||
if(service.saveEmail(email, user.getId())) {
|
||||
user.setEmail(email);
|
||||
return RestBean.success();
|
||||
} else {
|
||||
return RestBean.failure(400, "邮件地址已被其他用户使用,无法修改");
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/email")
|
||||
public RestBean<String> email(@SessionAttribute("account") AccountUser user){
|
||||
return RestBean.success(user.getEmail());
|
||||
}
|
||||
|
||||
@PostMapping("/save-password")
|
||||
public RestBean<String> savePassword(@Length(min = 6, max = 16) @RequestParam("old") String pass_old,
|
||||
@Length(min = 6, max = 16) @RequestParam("new") String pass_new,
|
||||
@SessionAttribute("account") AccountUser user){
|
||||
if (service.changePassword(pass_old, pass_new, user.getId())) {
|
||||
return RestBean.success();
|
||||
} else {
|
||||
return RestBean.failure(400, "原密码错误");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,15 @@
|
||||
package com.example.entity.user;
|
||||
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
@Data
|
||||
public class AccountInfo {
|
||||
private static final String USERNAME_REGEX = "^[a-zA-Z0-9一-龥]+$";
|
||||
|
||||
int uid;
|
||||
@Pattern(regexp = USERNAME_REGEX)
|
||||
@Length(min = 2, max = 8)
|
||||
String username;
|
||||
String sex;
|
||||
|
@ -13,6 +13,9 @@ public interface UserMapper {
|
||||
@Select("select * from db_account where username = #{text} or email = #{text}")
|
||||
Account findAccountByNameOrEmail(String text);
|
||||
|
||||
@Select("select * from db_account where id = #{id}")
|
||||
Account findAccountById(int id);
|
||||
|
||||
@Select("select * from db_account where username = #{text} or email = #{text}")
|
||||
AccountUser findAccountUserByNameOrEmail(String text);
|
||||
|
||||
@ -35,4 +38,10 @@ public interface UserMapper {
|
||||
|
||||
@Select("select * from db_account_info left join db_account on id = uid where id = #{uid}")
|
||||
AccountInfo findInfoById(int uid);
|
||||
|
||||
@Update("update db_account set email=#{email} where id=#{uid}")
|
||||
void updateEmail(String email, int uid);
|
||||
|
||||
@Update("update db_account set password=#{password} where id=#{uid}")
|
||||
void updatePassword(String password, int uid);
|
||||
}
|
||||
|
@ -5,4 +5,6 @@ import com.example.entity.user.AccountInfo;
|
||||
public interface UserService {
|
||||
boolean saveUserInfo(AccountInfo info);
|
||||
AccountInfo userInfo(int uid);
|
||||
boolean saveEmail(String email, int uid);
|
||||
boolean changePassword(String old, String _new, int uid);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import com.example.entity.user.AccountInfo;
|
||||
import com.example.mapper.UserMapper;
|
||||
import com.example.service.UserService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@ -12,6 +13,8 @@ public class UserServiceImpl implements UserService {
|
||||
@Resource
|
||||
UserMapper mapper;
|
||||
|
||||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||
|
||||
@Override
|
||||
public boolean saveUserInfo(AccountInfo info) {
|
||||
Account account = mapper.findAccountByNameOrEmail(info.getUsername());
|
||||
@ -28,4 +31,25 @@ public class UserServiceImpl implements UserService {
|
||||
public AccountInfo userInfo(int uid) {
|
||||
return mapper.findInfoById(uid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveEmail(String email, int uid) {
|
||||
Account account = mapper.findAccountByNameOrEmail(email);
|
||||
if(account == null) {
|
||||
mapper.updateEmail(email, uid);
|
||||
} else return account.getId() == uid;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean changePassword(String old, String _new, int uid) {
|
||||
Account account = mapper.findAccountById(uid);
|
||||
if (encoder.matches(old, account.getPassword())) {
|
||||
String encode = encoder.encode(_new);
|
||||
mapper.updatePassword(encode, uid);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,79 @@
|
||||
<script setup>
|
||||
import {reactive} from "vue";
|
||||
import {onMounted, reactive, ref} from "vue";
|
||||
import {Lock, Message, Select} from "@element-plus/icons-vue";
|
||||
import {get, logout, post} from "@/net";
|
||||
import {ElMessage} from "element-plus";
|
||||
|
||||
const securityForm = reactive({
|
||||
email: '',
|
||||
email: null,
|
||||
password_old: '',
|
||||
password_new: '',
|
||||
password_new_repeat: '',
|
||||
})
|
||||
|
||||
const emailForm = ref()
|
||||
const saveEmail = () => {
|
||||
emailForm.value.validate((isValid) => {
|
||||
if(isValid) {
|
||||
post('/api/user/save-email', {email: securityForm.email},
|
||||
() => ElMessage.success("保存成功!"))
|
||||
} else {
|
||||
ElMessage.warning('邮件格式有误,请正确填写')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const passwordForm = ref()
|
||||
const changePassword = () => {
|
||||
passwordForm.value.validate((isValid) => {
|
||||
if(isValid) {
|
||||
post('/api/user/save-password', {
|
||||
old: securityForm.password_old,
|
||||
new: securityForm.password_new
|
||||
}, () => {
|
||||
ElMessage.success('密码修改成功,请重新登录!')
|
||||
logout()
|
||||
})
|
||||
} else {
|
||||
ElMessage.warning('密码校验失败,请检查是否正确填写')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if(securityForm.email == null) {
|
||||
get('/api/user/email', message => securityForm.email = message)
|
||||
}
|
||||
})
|
||||
|
||||
const validatePassword = (rule, value, callback) => {
|
||||
if (value === '') {
|
||||
callback(new Error('请再次输入密码'))
|
||||
} else if (value !== securityForm.password_new) {
|
||||
callback(new Error("两次输入的密码不一致"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
const rules = {
|
||||
password_old: [
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||
{ min: 6, max: 16, message: '密码的长度必须在6-16个字符之间', trigger: ['blur', 'change'] }
|
||||
],
|
||||
password_new: [
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||
{ min: 6, max: 16, message: '密码的长度必须在6-16个字符之间', trigger: ['blur', 'change'] }
|
||||
],
|
||||
password_new_repeat: [
|
||||
{ required: true, message: '请再次输入密码', trigger: 'blur' },
|
||||
{ validator: validatePassword, trigger: ['blur', 'change'] },
|
||||
],
|
||||
email: [
|
||||
{ required: true, message: '请输入邮件地址', trigger: 'blur' },
|
||||
{ type: 'email', message: '请输入合法的电子邮件地址', trigger: ['blur', 'change']}
|
||||
]
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -15,35 +81,39 @@ const securityForm = reactive({
|
||||
<div>
|
||||
<h1><el-icon><Message/></el-icon> 邮箱设置</h1>
|
||||
<el-form
|
||||
ref="emailForm"
|
||||
:rules="rules"
|
||||
label-position="top"
|
||||
label-width="100px"
|
||||
:model="securityForm"
|
||||
style="max-width: 460px">
|
||||
<el-form-item label="邮箱地址">
|
||||
<el-form-item label="邮箱地址" prop="email">
|
||||
<el-input v-model="securityForm.email" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button type="success" :icon="Select">保存邮件地址</el-button>
|
||||
<el-button type="success" :icon="Select" @click="saveEmail">保存邮件地址</el-button>
|
||||
</div>
|
||||
<el-divider/>
|
||||
<div>
|
||||
<h1><el-icon><Lock/></el-icon> 密码设置</h1>
|
||||
<el-form
|
||||
ref="passwordForm"
|
||||
:rules="rules"
|
||||
label-position="top"
|
||||
label-width="100px"
|
||||
:model="securityForm"
|
||||
style="max-width: 460px">
|
||||
<el-form-item label="原密码">
|
||||
<el-input v-model="securityForm.password_old" />
|
||||
<el-form-item prop="password_old" label="原密码">
|
||||
<el-input type="password" show-password v-model="securityForm.password_old" />
|
||||
</el-form-item>
|
||||
<el-form-item label="新密码">
|
||||
<el-input v-model="securityForm.password_old" />
|
||||
<el-form-item prop="password_new" label="新密码">
|
||||
<el-input type="password" show-password v-model="securityForm.password_new" />
|
||||
</el-form-item>
|
||||
<el-form-item label="重复新密码">
|
||||
<el-input v-model="securityForm.password_old" />
|
||||
<el-form-item prop="password_new_repeat" label="重复新密码">
|
||||
<el-input type="password" show-password v-model="securityForm.password_new_repeat" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button type="success" :icon="Select">修改密码</el-button>
|
||||
<el-button type="success" :icon="Select" @click="changePassword">修改密码</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -41,4 +41,13 @@ function get(url, success, failure = defaultFailure, error = defaultError) {
|
||||
}).catch(error)
|
||||
}
|
||||
|
||||
export { get, post }
|
||||
const logout = () => {
|
||||
get('/api/auth/logout', (message) => {
|
||||
ElMessage.success(message)
|
||||
store.auth.user = null
|
||||
localStorage.removeItem('user')
|
||||
router.push('/')
|
||||
})
|
||||
}
|
||||
|
||||
export { get, post, logout }
|
||||
|
@ -84,8 +84,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {get} from "@/net";
|
||||
import {ElMessage} from "element-plus";
|
||||
import {logout} from "@/net";
|
||||
import router from "@/router";
|
||||
import {useStore} from "@/stores";
|
||||
import {Document, Setting, Menu as IconMenu, Search, Back, Expand, Fold} from "@element-plus/icons-vue";
|
||||
@ -94,15 +93,6 @@ import {ref} from "vue";
|
||||
const store = useStore()
|
||||
|
||||
const isCollapse = ref(false)
|
||||
|
||||
const logout = () => {
|
||||
get('/api/auth/logout', (message) => {
|
||||
ElMessage.success(message)
|
||||
store.auth.user = null
|
||||
localStorage.removeItem('user')
|
||||
router.push('/')
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
Loading…
x
Reference in New Issue
Block a user