springboot框架课学习笔记:第四讲 配置mysql与注册登录模块(中)
二刷
这节课的内容主要是用户的登录与注册,实现三个 API
- 登录 获取令牌
- 获取用户的信息
- 注册账号
URL
- 公开
- login 与数据库一致,返回 sessionId
- register 注册成功,返回 login 界面
- 授权
- 判断 sessionId 是否有效 => 将 user 提取到上下文 => 访问 controller 。
jwt token 验证
- 可以解决跨域问题
- 不需要再服务器端存储
JWT Token 登录参考文章 https://zhuanlan.zhihu.com/p/443618267
- JWT 概念 : 定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的
- Token 组成 : header, payload, signature
- JWT token 与 session , cookie 的优缺点比较
- JWT 适用于 分布式,存储在浏览器中
java中的注解大全@controller、@service、@repository等 参考文章https://www.cnblogs.com/CrisZjie180228/p/8745603.html
-
@Controller 用于标记在一个类上,使用它标记的类就是一个SpringMVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法。
通俗来说,被Controller标记的类就是一个控制器,这个类中的方法,就是相应的动作。 -
@RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
与 @Controller 组合使用。 -
service采用@service注解
- 例:@Service("userService")注解是告诉Spring,当Spring要创建UserServiceImpl的的实例时,bean的名字必须叫做"userService",
这样当Action需要使用UserServiceImpl的的实例时,就可以由Spring创建好的"userService",然后注入给Action。
- 例:@Service("userService")注解是告诉Spring,当Spring要创建UserServiceImpl的的实例时,bean的名字必须叫做"userService",
-
@Autowired : 它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 通过 @Autowired的使用来消除 set ,get方法。
405 错误什么意思?
- 方法不被允许。比如 get 请求 使用 post
-------- 二刷分割线
登录模块设计
jwt验证方式 解决跨域问题
**浏览器快速切换页面快捷键 CTRL + tab **
// jwt工具类,创建解析 jwt token
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;
@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();
}
}
验证jwt-token是否合法,如果合法就自动将user提取到上下文中 轮子如下
package com.kob.backend.config.filter;
import com.kob.backend.mapper.UserMapper;
import com.kob.backend.pojo.User;
import com.kob.backend.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);
}
}
alt 回车 导入类
说出每一步代码的作用,做注释
写一个接口,service写接口,写实现,controller 里面写一个类
usercontroller 调试用的,可以删掉
** autoweired 按类型注入 resource按名称注入**
实现 一层调用一层
405错误 方法未被允许
500 错误 服务器报错
403错误是一种在网站访问过程中,常见的错误提示,表示资源不可用。 服务器理解客户的请求,但拒绝处理它,通常由于服务器上文件或目录的权限设置导致的WEB访问错误。
Authorization 授权 Authentication 认证
package com.kob.backend.service.impl.user.account;
import com.kob.backend.pojo.User;
import com.kob.backend.service.impl.utils.UserDetailsImpl;
import com.kob.backend.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;
@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);
// 验证是否可以正常登录 var api 自动定义变量名,类型名字
Authentication authenticate = authenticationManager.authenticate(authenticationToken);
// 如果报错会自动处理·
// 取出用户
UserDetailsImpl loginUser=(UserDetailsImpl) authenticate.getPrincipal();
User user=loginUser.getUser();
// 封装用户id 成为jwt token
String jwt= JwtUtil.createJWT(user.getId().toString());
//成功之后定义返回结果 注意和前端对应
Map<String,String> map=new HashMap<>();
map.put("error_message","success");
map.put("token",jwt);
System.out.println("jwt "+jwt+" test");
return map;
}
}
package com.kob.backend.controller.user.account;
import com.kob.backend.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.Map;
@RestController
public class LoginController {
// 注入定义的接口
@Autowired
private LoginService loginService;
// 登录 post请求。 定义之后记得公开化 放行 。记得改名 get token
@PostMapping("/user/account/token/")
public Map<String,String> getToken(@RequestParam Map<String,String>map) {
// getToken 传递两个信息 post请求参数放到map中 (使用注解)
String username=map.get("username");
String password=map.get("password");
// 调用接口
System.out.println("login test "+username+" "+password);
return loginService.getToken(username,password);
}
}
map是个集合。map.put() 存放元素
遇到的问题 vue请求后端返回的数据res[object object] (我要走的更远)
经过自己的检验,好像是后端出现了问题。把y总的backend换了下,可以正常运行
玄学错误 最后复制y总代码解决
System grid 布局格式。 居中 row justify-content-md-center
然后是居中的形式
当自己觉得很困难的时候,是自己给自己开了hard模式。想办法去解决。生活重新教做人,重新指出该走的路。
肯定不会这么困难的,也不要想这么多,把看到的背下来,抓住真实。
学习 前端user.js getinof函数。获取信息
token存在于本地,服务器端没有存储
用户退出登录 删除token。
同步函数 调用mutation。异步函数 调用action。
token存储到 localStorage,退出浏览器与刷新 不会需要重新登录。
第四章内容总结。有MySQL,mybatis plus,jwt验证,前端。
回调函数 执行之后会调用函数。