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。
  • @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验证,前端。
回调函数 执行之后会调用函数。

posted @ 2023-01-03 10:08  安半愚  阅读(115)  评论(0)    收藏  举报