parent
7380bf236a
commit
66c9c9f38c
24 changed files with 800 additions and 84 deletions
@ -1,22 +1,51 @@ |
||||
package com.kob.backend.config; |
||||
|
||||
|
||||
|
||||
import com.kob.backend.config.filter.JwtAuthenticationTokenFilter; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.http.HttpMethod; |
||||
import org.springframework.security.authentication.AuthenticationManager; |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; |
||||
import org.springframework.security.config.http.SessionCreationPolicy; |
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; |
||||
import org.springframework.security.crypto.password.PasswordEncoder; |
||||
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; |
||||
|
||||
/** |
||||
* @author zfp |
||||
*/ |
||||
|
||||
@Configuration |
||||
@EnableWebSecurity |
||||
public class SecurityConfig { |
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter { |
||||
@Autowired |
||||
private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; |
||||
|
||||
@Bean |
||||
public PasswordEncoder passwordEncoder() { |
||||
return new BCryptPasswordEncoder(); |
||||
} |
||||
} |
||||
|
||||
@Bean |
||||
@Override |
||||
public AuthenticationManager authenticationManagerBean() throws Exception { |
||||
return super.authenticationManagerBean(); |
||||
} |
||||
|
||||
@Override |
||||
protected void configure(HttpSecurity http) throws Exception { |
||||
http.csrf().disable() |
||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) |
||||
.and() |
||||
.authorizeRequests() |
||||
.antMatchers("/user/account/token/", "/user/account/register/").permitAll() |
||||
.antMatchers(HttpMethod.OPTIONS).permitAll() |
||||
.anyRequest().authenticated(); |
||||
|
||||
http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); |
||||
} |
||||
} |
||||
|
@ -0,0 +1,63 @@ |
||||
package com.kob.backend.config.filter; |
||||
|
||||
/** |
||||
* @author zfp |
||||
*/ |
||||
import com.kob.backend.mapper.UserMapper; |
||||
import com.kob.backend.controller.pojo.User; |
||||
import com.kob.backend.controller.service.impl.utils.UserDetailsImpl; |
||||
import com.kob.backend.utils.JwtUtil; |
||||
import io.jsonwebtoken.Claims; |
||||
import org.jetbrains.annotations.NotNull; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; |
||||
import org.springframework.security.core.context.SecurityContextHolder; |
||||
import org.springframework.stereotype.Component; |
||||
import org.springframework.util.StringUtils; |
||||
import org.springframework.web.filter.OncePerRequestFilter; |
||||
|
||||
import javax.servlet.FilterChain; |
||||
import javax.servlet.ServletException; |
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.IOException; |
||||
|
||||
@Component |
||||
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { |
||||
@Autowired |
||||
private UserMapper userMapper; |
||||
|
||||
@Override |
||||
protected void doFilterInternal(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain filterChain) throws ServletException, IOException { |
||||
String token = request.getHeader("Authorization"); |
||||
|
||||
if (!StringUtils.hasText(token) || !token.startsWith("Bearer ")) { |
||||
filterChain.doFilter(request, response); |
||||
return; |
||||
} |
||||
|
||||
token = token.substring(7); |
||||
|
||||
String userid; |
||||
try { |
||||
Claims claims = JwtUtil.parseJWT(token); |
||||
userid = claims.getSubject(); |
||||
} catch (Exception e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
|
||||
User user = userMapper.selectById(Integer.parseInt(userid)); |
||||
|
||||
if (user == null) { |
||||
throw new RuntimeException("用户名未登录"); |
||||
} |
||||
|
||||
UserDetailsImpl loginUser = new UserDetailsImpl(user); |
||||
UsernamePasswordAuthenticationToken authenticationToken = |
||||
new UsernamePasswordAuthenticationToken(loginUser, null, null); |
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(authenticationToken); |
||||
|
||||
filterChain.doFilter(request, response); |
||||
} |
||||
} |
@ -0,0 +1,36 @@ |
||||
package com.kob.backend.controller.service.impl.user.account; |
||||
|
||||
import com.kob.backend.controller.pojo.User; |
||||
import com.kob.backend.controller.service.impl.utils.UserDetailsImpl; |
||||
import com.kob.backend.controller.service.user.account.InfoService; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; |
||||
import org.springframework.security.core.context.SecurityContextHolder; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author zfp |
||||
*/ |
||||
@Service |
||||
public class InfoServiceImpl implements InfoService { |
||||
@Override |
||||
public Map<String, String> getInfo() { |
||||
UsernamePasswordAuthenticationToken authenticationToken = |
||||
(UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); |
||||
// 获得登陆的用户信息
|
||||
UserDetailsImpl loginUser = (UserDetailsImpl) authenticationToken.getPrincipal(); |
||||
// 提取用户
|
||||
User user = loginUser.getUser(); |
||||
|
||||
Map<String,String> map = new HashMap<>(); |
||||
// 返回验证后的用户信息
|
||||
map.put("error_msg","success"); |
||||
map.put("id",user.getId().toString()); |
||||
map.put("username",user.getUsername()); |
||||
map.put("photo",user.getPhoto()); |
||||
return map; |
||||
} |
||||
} |
@ -0,0 +1,48 @@ |
||||
package com.kob.backend.controller.service.impl.user.account; |
||||
|
||||
|
||||
|
||||
import com.kob.backend.controller.pojo.User; |
||||
import com.kob.backend.controller.service.impl.utils.UserDetailsImpl; |
||||
import com.kob.backend.controller.service.user.account.LoginService; |
||||
import com.kob.backend.utils.JwtUtil; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.security.authentication.AuthenticationManager; |
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; |
||||
import org.springframework.security.core.Authentication; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author zfp |
||||
*/ |
||||
@Service |
||||
public class LoginServiceImpl implements LoginService { |
||||
|
||||
@Autowired |
||||
private AuthenticationManager authenticationManager; |
||||
|
||||
@Override |
||||
public Map<String, String> getToken(String username, String password) { |
||||
// 使用下面代码将用户名和密码(密文)封装成一个类
|
||||
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username,password); |
||||
// 登陆验证,登陆失败会自动处理(抛出异常)
|
||||
Authentication authenticate = authenticationManager.authenticate(authenticationToken); |
||||
// 获取登陆的用户
|
||||
UserDetailsImpl loginUser = (UserDetailsImpl) authenticate.getPrincipal(); |
||||
|
||||
//
|
||||
User user = loginUser.getUser(); |
||||
|
||||
// 利用用户id这个信息创建一个token
|
||||
String jwt = JwtUtil.createJWT(user.getId().toString()); |
||||
|
||||
Map<String,String> res = new HashMap<>(); |
||||
|
||||
res.put("error_msg","success"); |
||||
res.put("token",jwt); |
||||
return res; |
||||
} |
||||
} |
@ -0,0 +1,88 @@ |
||||
package com.kob.backend.controller.service.impl.user.account; |
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
||||
import com.kob.backend.controller.pojo.User; |
||||
import com.kob.backend.controller.service.user.account.RegisterService; |
||||
import com.kob.backend.mapper.UserMapper; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.security.crypto.password.PasswordEncoder; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author zfp |
||||
*/ |
||||
@Service |
||||
public class RegisterServiceImpl implements RegisterService { |
||||
@Autowired |
||||
private UserMapper userMapper; |
||||
|
||||
@Autowired |
||||
private PasswordEncoder passwordEncoder; |
||||
@Override |
||||
public Map<String, String> register(String username, String password, String confirmedPassword) { |
||||
final int MAX_USERNAME_LEN = 100; |
||||
Map<String, String> map = new HashMap<>(); |
||||
if (username == null) { |
||||
map.put("error_msg","用户名不能为空!"); |
||||
return map; |
||||
} |
||||
|
||||
if (password == null || confirmedPassword == null) { |
||||
map.put("error_msg","密码不能为空!"); |
||||
return map; |
||||
} |
||||
|
||||
// 去除首尾空格
|
||||
username = username.trim(); |
||||
|
||||
if (username.length() == 0) { |
||||
map.put("error_msg","用户名不能为空!"); |
||||
return map; |
||||
} |
||||
|
||||
if (password.length() == 0 || confirmedPassword.length() == 0) { |
||||
map.put("error_msg","密码不能为空!"); |
||||
return map; |
||||
} |
||||
|
||||
if (username.length() > MAX_USERNAME_LEN) { |
||||
map.put("error_msg","用户名长度不能大于100!"); |
||||
return map; |
||||
} |
||||
|
||||
if (password.length() > MAX_USERNAME_LEN || confirmedPassword.length() > MAX_USERNAME_LEN) { |
||||
map.put("error_msg","密码长度不能超过100!"); |
||||
return map; |
||||
} |
||||
|
||||
if (!password.equals(confirmedPassword)) { |
||||
map.put("error_msg","两次输入的密码不一致!"); |
||||
return map; |
||||
} |
||||
|
||||
QueryWrapper<User> qw = new QueryWrapper<>(); |
||||
// 查询是否该用户名已被使用
|
||||
qw.eq("username",username); |
||||
List<User> list = userMapper.selectList(qw); |
||||
|
||||
if (!list.isEmpty()) { |
||||
map.put("error_msg","该用户名已被使用!"); |
||||
return map; |
||||
} |
||||
// 将用户密码加密
|
||||
String encodedPassword = passwordEncoder.encode(password); |
||||
String photo = "https://cdn.acwing.com/media/user/profile/photo/41648_lg_8d1ad446b6.jpg"; |
||||
User user = new User(null,username,encodedPassword,photo); |
||||
// 将用户数据存入数据库
|
||||
userMapper.insert(user); |
||||
|
||||
// 返回success表示注册成功
|
||||
map.put("error_msg","success!"); |
||||
return map; |
||||
|
||||
} |
||||
} |
@ -0,0 +1,13 @@ |
||||
package com.kob.backend.controller.service.user.account; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author zfp |
||||
*/ |
||||
public interface InfoService { |
||||
/** |
||||
* @return userInfo |
||||
*/ |
||||
Map<String, String> getInfo(); |
||||
} |
@ -0,0 +1,10 @@ |
||||
package com.kob.backend.controller.service.user.account; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author zfp |
||||
*/ |
||||
public interface LoginService { |
||||
Map<String,String> getToken(String username, String password); |
||||
} |
@ -0,0 +1,10 @@ |
||||
package com.kob.backend.controller.service.user.account; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author zfp |
||||
*/ |
||||
public interface RegisterService { |
||||
Map<String,String> register(String username,String password,String confirmedPassword); |
||||
} |
@ -1,72 +0,0 @@ |
||||
package com.kob.backend.controller.user; |
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
||||
import com.kob.backend.controller.pojo.User; |
||||
import com.kob.backend.mapper.UserMapper; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; |
||||
import org.springframework.security.crypto.password.PasswordEncoder; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.PathVariable; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @author zfp |
||||
*/ |
||||
@RestController |
||||
public class UserController { |
||||
|
||||
@Autowired |
||||
UserMapper userMapper; |
||||
|
||||
// 返回user表的所有数据
|
||||
@GetMapping("/user/all/") |
||||
public List<User> getAll() { |
||||
|
||||
return userMapper.selectList(null); |
||||
} |
||||
|
||||
// 返回指定id的用户信息
|
||||
@GetMapping("/user/{userId}/") |
||||
public User getUser(@PathVariable int userId) { |
||||
|
||||
QueryWrapper<User> qw = new QueryWrapper<>(); |
||||
// 返回指定id的用户信息
|
||||
// return userMapper.selectById(userId);
|
||||
|
||||
// 等价于上面的查询语句
|
||||
qw.eq("id",userId); |
||||
|
||||
// 返回编号大于等于2小于等于3的所有用户信息
|
||||
// qw.ge("id",2).le("id",3);
|
||||
return userMapper.selectOne(qw); |
||||
} |
||||
|
||||
// 添加用户
|
||||
@GetMapping("/user/add/{userid}/{username}/{password}/") |
||||
public String addUser(@PathVariable int userid, |
||||
@PathVariable String username, |
||||
@PathVariable String password) { |
||||
// 存入数据库直接存入的是密文,不存明文密码
|
||||
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); |
||||
String encodedPassword = passwordEncoder.encode(password); |
||||
User user = new User(userid,username,encodedPassword); |
||||
userMapper.insert(user); |
||||
return "Add User Successfully!"; |
||||
|
||||
} |
||||
|
||||
// 删除用户
|
||||
|
||||
@GetMapping("/user/delete/{userid}") |
||||
public String deleteUser(@PathVariable int userid) { |
||||
userMapper.deleteById(userid); |
||||
return "Delete User Successfully!"; |
||||
} |
||||
|
||||
|
||||
} |
||||
|
@ -0,0 +1,22 @@ |
||||
package com.kob.backend.controller.user.account; |
||||
|
||||
import com.kob.backend.controller.service.user.account.InfoService; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author zfp |
||||
*/ |
||||
@RestController |
||||
public class InfoServiceController { |
||||
@Autowired |
||||
private InfoService infoService; |
||||
|
||||
@GetMapping("/user/account/info/") |
||||
public Map<String, String> getInfo() { |
||||
return infoService.getInfo(); |
||||
} |
||||
} |
@ -0,0 +1,30 @@ |
||||
package com.kob.backend.controller.user.account; |
||||
|
||||
import com.kob.backend.controller.service.user.account.LoginService; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.web.bind.annotation.PostMapping; |
||||
import org.springframework.web.bind.annotation.RequestParam; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author zfp |
||||
*/ |
||||
@RestController |
||||
public class LoginController { |
||||
@Autowired |
||||
private LoginService loginService; |
||||
|
||||
@PostMapping("/user/account/token/") |
||||
// 利用RequestParam注解将用户名和密码存到一个Map中
|
||||
public Map<String ,String> getToken(@RequestParam Map<String,String> map) { |
||||
String username = map.get("username"); |
||||
String password = map.get("password"); |
||||
// 调用接口获得jwt_token
|
||||
return loginService.getToken(username,password); |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,28 @@ |
||||
package com.kob.backend.controller.user.account; |
||||
|
||||
import com.kob.backend.controller.service.user.account.RegisterService; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.web.bind.annotation.PostMapping; |
||||
import org.springframework.web.bind.annotation.RequestParam; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author zfp |
||||
*/ |
||||
@RestController |
||||
public class RegisterController{ |
||||
@Autowired |
||||
private RegisterService registerService; |
||||
|
||||
@PostMapping("/user/account/register/") |
||||
|
||||
public Map<String,String> register(@RequestParam Map<String,String> map) { |
||||
String username = map.get("username"); |
||||
String password = map.get("password"); |
||||
String confirmedPassword = map.get("confirmedPassword"); |
||||
return registerService.register(username,password,confirmedPassword); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,66 @@ |
||||
package com.kob.backend.utils; |
||||
|
||||
|
||||
import io.jsonwebtoken.Claims; |
||||
import io.jsonwebtoken.JwtBuilder; |
||||
import io.jsonwebtoken.Jwts; |
||||
import io.jsonwebtoken.SignatureAlgorithm; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import javax.crypto.SecretKey; |
||||
import javax.crypto.spec.SecretKeySpec; |
||||
import java.util.Base64; |
||||
import java.util.Date; |
||||
import java.util.UUID; |
||||
|
||||
/** |
||||
* @author zfp |
||||
*/ |
||||
@Component |
||||
public class JwtUtil { |
||||
public static final long JWT_TTL = 60 * 60 * 1000L * 24 * 14; // 有效期14天
|
||||
public static final String JWT_KEY = "SDFGjhdsfalshdfHFdsjkdsfds121232131afasdfac"; |
||||
|
||||
public static String getUUID() { |
||||
return UUID.randomUUID().toString().replaceAll("-", ""); |
||||
} |
||||
|
||||
public static String createJWT(String subject) { |
||||
JwtBuilder builder = getJwtBuilder(subject, null, getUUID()); |
||||
return builder.compact(); |
||||
} |
||||
|
||||
private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) { |
||||
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; |
||||
SecretKey secretKey = generalKey(); |
||||
long nowMillis = System.currentTimeMillis(); |
||||
Date now = new Date(nowMillis); |
||||
if (ttlMillis == null) { |
||||
ttlMillis = JwtUtil.JWT_TTL; |
||||
} |
||||
|
||||
long expMillis = nowMillis + ttlMillis; |
||||
Date expDate = new Date(expMillis); |
||||
return Jwts.builder() |
||||
.setId(uuid) |
||||
.setSubject(subject) |
||||
.setIssuer("sg") |
||||
.setIssuedAt(now) |
||||
.signWith(signatureAlgorithm, secretKey) |
||||
.setExpiration(expDate); |
||||
} |
||||
|
||||
public static SecretKey generalKey() { |
||||
byte[] encodeKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY); |
||||
return new SecretKeySpec(encodeKey, 0, encodeKey.length, "HmacSHA256"); |
||||
} |
||||
|
||||
public static Claims parseJWT(String jwt) throws Exception { |
||||
SecretKey secretKey = generalKey(); |
||||
return Jwts.parserBuilder() |
||||
.setSigningKey(secretKey) |
||||
.build() |
||||
.parseClaimsJws(jwt) |
||||
.getBody(); |
||||
} |
||||
} |
@ -0,0 +1,86 @@ |
||||
import $ from 'jquery' |
||||
|
||||
export default { |
||||
state: { // 全局变量
|
||||
id: "", |
||||
username: "", |
||||
photo: "", |
||||
token: "", |
||||
is_login: false, // 默认未登录状态
|
||||
}, |
||||
getters: { |
||||
}, |
||||
mutations: { // 用于修改全局数据
|
||||
updateUser(state,user) { // 更新用户信息
|
||||
state.id = user.id; |
||||
state.username = user.username; |
||||
state.photo = user.photo; |
||||
state.is_login = user.is_login; |
||||
}, |
||||
updateToken(state,token) { // 更新token
|
||||
state.token = token; |
||||
}, |
||||
logout(state) { |
||||
state.id = ""; |
||||
state.username = ""; |
||||
state.photo = ""; |
||||
state.token = ""; |
||||
state.is_login = false; |
||||
} |
||||
}, |
||||
actions: { // 在actions中调用修改全局变量的函数
|
||||
login(context,data) { |
||||
$.ajax({ |
||||
url: "http://localhost:3000/user/account/token/", |
||||
type : "POST", |
||||
data: { |
||||
username: data.username, |
||||
password: data.password, |
||||
}, |
||||
success(resp) {
|
||||
// resp对应的就是后端的map的json格式,每个字段对应键值对中的key
|
||||
// 登陆成功
|
||||
if(resp.error_msg === "success"){ |
||||
// 调用updateToken函数,形参中的data为resp.token
|
||||
context.commit("updateToken",resp.token); |
||||
data.success(resp); |
||||
}else { |
||||
data.error(resp); |
||||
} |
||||
}, |
||||
error(resp) { |
||||
data.error(resp); |
||||
}, |
||||
}); |
||||
}, |
||||
getInfo(context,data) { |
||||
$.ajax({ |
||||
url: "http://localhost:3000/user/account/info/", |
||||
type: "GET", |
||||
headers: { |
||||
Authorization: "Bearer " + context.state.token, |
||||
}, |
||||
success(resp) {
|
||||
if (resp.error_msg === "success"){ |
||||
// 登陆成功后,更新当前用户信息
|
||||
context.commit("updateUser",{ |
||||
...resp, |
||||
is_login: true, |
||||
}); |
||||
data.success(resp); // 调用UserLoginView中的success()回调函数
|
||||
}else { |
||||
data.error(resp); // 调用UserLoginView中的error()回调函数
|
||||
} |
||||
}, |
||||
error(resp) { |
||||
data.error(resp); |
||||
}, |
||||
}); |
||||
}, |
||||
logout(context) { |
||||
context.commit("logout"); // 退出登录
|
||||
} |
||||
}, |
||||
modules: { |
||||
} |
||||
} |
@ -0,0 +1,87 @@ |
||||
<template> |
||||
<ContentField> |
||||
<div class="row justify-content-md-center"> |
||||
<div class="col-3"> |
||||
<form @submit.prevent="login"> |
||||
<div class="mb-3"> |
||||
<label for="username" class="form-label">用户名</label> |
||||
<!--使用v-model绑定下面的变量,input中的值传递给username变量--> |
||||
<input |
||||
v-model="username" |
||||
type="text" |
||||
class="form-control" |
||||
id="username" |
||||
placeholder="请输入用户名" |
||||
/> |
||||
</div> |
||||
<div class="mb-3"> |
||||
<label for="password" class="form-label">密码</label> |
||||
<input v-model="password" |
||||
type="password" class="form-control" id="password" placeholder="请输入密码"/> |
||||
</div> |
||||
<div class="error-messsage"> {{error_msg}} </div> |
||||
<button type="submit" class="btn btn-primary btn-sm">登录</button> |
||||
</form> |
||||
</div> |
||||
</div> |
||||
</ContentField> |
||||
</template> |
||||
|
||||
<script> |
||||
import ContentField from "@/components/ContentField.vue"; |
||||
import { useStore } from "vuex"; |
||||
import { ref } from "vue"; |
||||
import router from '@/router/index'; |
||||
|
||||
export default { |
||||
components: { |
||||
ContentField, |
||||
}, |
||||
setup() { |
||||
const store = useStore(); |
||||
let username = ref(''); |
||||
let password = ref(''); |
||||
let error_msg = ref(''); |
||||
|
||||
// 定义触发函数: 提交表单时触发login函数 |
||||
const login = () => { |
||||
error_msg.value = ""; |
||||
// error_msg.value = ""; // 清空上一次的错误信息 |
||||
// 利用store调用actions中的函数,第一个参数时调用的函数名,第二个参数需要传入一些数据和一些回调函数 |
||||
store.dispatch("login",{ |
||||
username: username.value, |
||||
password:password.value, |
||||
success(){ // 登陆成功直接跳转到主页面 |
||||
store.dispatch("getInfo",{ |
||||
success() { |
||||
router.push({name:"home"}); |
||||
console.log(store.state.user); |
||||
} |
||||
}); |
||||
}, |
||||
error() { // 登陆失败 |
||||
error_msg.value = "用户名或密码错误!"; |
||||
} |
||||
}); |
||||
} |
||||
|
||||
return { |
||||
username, |
||||
password, |
||||
error_msg, |
||||
login, |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style scoped> |
||||
button { |
||||
width: 100%; |
||||
} |
||||
.error-messsage{ |
||||
margin-bottom: 10px; |
||||
color: red; |
||||
font-weight: bold; |
||||
} |
||||
</style> |
@ -0,0 +1,53 @@ |
||||
<template> |
||||
<ContentField> |
||||
<div class="row justify-content-md-center"> |
||||
<div class="col-3"> |
||||
<form > |
||||
<div class="mb-3"> |
||||
<label for="username" class="form-label">用户名</label> |
||||
<input |
||||
type="text" |
||||
class="form-control" |
||||
id="username" |
||||
placeholder="请输入用户名" |
||||
/> |
||||
</div> |
||||
<div class="mb-3"> |
||||
<label for="password" class="form-label">密码</label> |
||||
<input type="password" class="form-control" id="password" placeholder="请输入密码"/> |
||||
</div> |
||||
|
||||
<div class="mb-3"> |
||||
<label for="confirm_password" class="form-label">确认密码</label> |
||||
<input type="password" class="form-control" id="confirm_password" placeholder="再次输入一次密码"/> |
||||
</div> |
||||
<div class="error_msg">密码错误!</div> |
||||
<button type="submit" class="btn btn-primary btn-sm">注册</button> |
||||
</form> |
||||
</div> |
||||
</div> |
||||
</ContentField> |
||||
</template> |
||||
|
||||
<script> |
||||
|
||||
import ContentField from "@/components/ContentField.vue" |
||||
|
||||
|
||||
export default { |
||||
components: { |
||||
ContentField |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
button { |
||||
width: 100%; |
||||
} |
||||
.error_msg{ |
||||
margin-bottom: 10px; |
||||
color: red; |
||||
font-weight: bold; |
||||
} |
||||
</style> |
Loading…
Reference in new issue