• 【畅购商城】用户登录


      1. 用户登录
        1. 构建页面:Login.vue
    1. 步骤一:创建Login.vue

    1. 步骤二:绘制通用模块

    1. 步骤三:绘制登录表单

        1. 分析

        1. 验证码:接口

    http://localhost:10010/web-service/verifycode?username=jack

        1. 验证码:生成与显示
    1. 步骤一:后端生产验证码,并将用户保存Redis
      1. 存放redis中验证码key格式:"login" + 用户名

    package com.czxy.changgou4.controller;

    import org.springframework.data.redis.core.StringRedisTemplate;

    import org.springframework.stereotype.Controller;

    import org.springframework.web.bind.annotation.GetMapping;

    import org.springframework.web.bind.annotation.RequestMapping;

    import javax.annotation.Resource;

    import javax.imageio.ImageIO;

    import javax.servlet.http.HttpServletResponse;

    import java.awt.*;

    import java.awt.image.BufferedImage;

    import java.io.IOException;

    import java.util.Random;

    import java.util.concurrent.TimeUnit;

    /**

     * @author 桐叔

     * @email liangtong@itcast.cn

     */

    @Controller

    @RequestMapping("/verifycode")

    public class VerifyCodeController {

        @Resource

        private StringRedisTemplate stringRedisTemplate;

        @GetMapping

        public void verifyCode(String username , HttpServletResponse response ) throws IOException {

            //字体只显示大写,去掉了1,0,i,o几个容易混淆的字符

            String VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";

            int IMG_WIDTH = 72;

            int IMG_HEIGTH = 27;

            Random random = new Random();

            //创建图片

            BufferedImage image = new BufferedImage(IMG_WIDTH, IMG_HEIGTH, BufferedImage.TYPE_INT_RGB);

            //画板

            Graphics g = image.getGraphics();

            //填充背景

            g.setColor(Color.WHITE);

            g.fillRect(1,1,IMG_WIDTH-2,IMG_HEIGTH-2);

            g.setFont(new Font("楷体", Font.BOLD,25));

            StringBuilder sb = new StringBuilder();

            //写字

            for(int i = 1 ; i <= 4 ; i ++){

                //随机颜色

                g.setColor(new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)));

                int len = random.nextInt(VERIFY_CODES.length());

                String str = VERIFY_CODES.substring(len,len+1);

                sb.append(str);

                g.drawString(str, IMG_WIDTH / 6 * i , 22 );

            }

            //将验证码存放到redis

            stringRedisTemplate.opsForValue().set( "login" + username , sb.toString() , 1 , TimeUnit.HOURS);

            // 生成随机干扰线

            for (int i = 0; i < 30; i++) {

                //随机颜色

                g.setColor(new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)));

                int x = random.nextInt(IMG_WIDTH - 1);

                int y = random.nextInt(IMG_HEIGTH - 1);

                int x1 = random.nextInt(12) + 1;

                int y1 = random.nextInt(6) + 1;

                g.drawLine(x, y, x - x1, y - y1);

            }

            //响应到浏览器

            ImageIO.write(image,"jpeg", response.getOutputStream());

        }

    }

    1. 步骤二:点击“换一张”显示验证码
      1. 默认不显示验证码
      2. 点击“换一张”获得验证码

        1. 通过用户名查询:接口

    POST http://localhost:10010/web-service/user/findByUsername

    {

    "username":"jack"

    }

        1. 通过用户名查询:实现
    1. 修改UserController,添加 findByUsername函数

    /**

     * 通过用户名查询

     * @param user

     * @return 返回用户对象

     */

    @PostMapping("/findByUsername")

    public User findByUsername(@RequestBody User user){

        //查询用户

        User findUser = userService.findByUsername( user.getUsername() );

        return findUser;

    }

        1. 认证服务:构建项目(changgou4-service-auth)
    1. 步骤一:构建项目

    1. 步骤二:创建pom.xml文件

    <dependencies>

        

        <dependency>

            <groupId>com.czxy.changgougroupId>

            <artifactId>changgou4_common_authartifactId>

        dependency>

        

        <dependency>

            <groupId>org.springframework.bootgroupId>

            <artifactId>spring-boot-starter-webartifactId>

        dependency>

        

        <dependency>

            <groupId>com.alibaba.nacosgroupId>

            <artifactId>nacos-clientartifactId>

        dependency>

        

        <dependency>

            <groupId>com.alibaba.cloudgroupId>

            <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>

        dependency>

        

        <dependency>

            <groupId>org.springframework.bootgroupId>

            <artifactId>spring-boot-starter-data-redisartifactId>

        dependency>

        <dependency>

            <groupId>redis.clientsgroupId>

            <artifactId>jedisartifactId>

        dependency>

        

        <dependency>

            <groupId>io.springfoxgroupId>

            <artifactId>springfox-swagger2artifactId>

        dependency>

        <dependency>

            <groupId>io.springfoxgroupId>

            <artifactId>springfox-swagger-uiartifactId>

        dependency>

            

            

                org.springframework.cloud

                spring-cloud-starter-openfeign

            

    dependencies>

    1. 步骤三:创建yml文件

    server:

      port: 8085

    spring:

      application:

        name: auth-service

      cloud:

        nacos:

          discovery:

            server-addr: 127.0.0.1:8848   #nacos服务地址

    sc:

      jwt:

        secret: sc@Login(Auth}*^31)&czxy% # 登录校验的密钥

        pubKeyPath: D:/rsa/rsa.pub # 公钥地址

        priKeyPath: D:/rsa/rsa.pri # 私钥地址

        expire: 360 # 过期时间,单位分钟

    1. 步骤四:配置启动类

    package com.czxy.changgou4;

    import org.springframework.boot.SpringApplication;

    import org.springframework.boot.autoconfigure.SpringBootApplication;

    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

    import org.springframework.cloud.openfeign.EnableFeignClients;

    /**

     * @author 桐叔

     * @email liangtong@itcast.cn

     */

    @SpringBootApplication

    @EnableDiscoveryClient

    @EnableFeignClients

    public class CGAuthServiceApplication {

        public static void main(String[] args) {

            SpringApplication.run(CGAuthServiceApplication.class, args);

        }

    }

    1. 步骤五:配置类

        1. 认证服务:用户登录后端
    1. 步骤一:创建AuthUser 封装对象(与User比较,缺数据库相关注解)

    package com.czxy.changgou4.domain;

    import lombok.Data;

    import java.util.Date;

    /**

     * @author 桐叔

     * @email liangtong@itcast.cn

     */

    @Data

    public class AuthUser {

        private Long id;

        private String username;

        private String password;

        private String face;

        private Integer expriece;

        private String email;

        private String mobile;

        private Date createdAt;

        private Date updatedAt;

        private String code;

        private String password_confirm;

    }

    1. 步骤二:创建UserFeign,完成远程用户查询功能

    package com.czxy.changgou4.feign;

    import com.czxy.changgou4.domain.AuthUser;

    import org.springframework.cloud.openfeign.FeignClient;

    import org.springframework.web.bind.annotation.PostMapping;

    import org.springframework.web.bind.annotation.RequestBody;

    /**

     * @author 桐叔

     * @email liangtong@itcast.cn

     */

    @FeignClient(value = "web-service",path="/user")

    public interface UserFeign {

        @PostMapping("/findByUsername")

        public AuthUser findByUsername(@RequestBody AuthUser user);

    }

    1. 步骤三:创建AuthService接口,编写登录方法 login()

    package com.czxy.changgou4.service;

    import com.czxy.changgou4.domain.AuthUser;

    /**

     * @author 桐叔

     * @email liangtong@itcast.cn

     */

    public interface AuthService {

        /**

         * 用户登录

         * @param user

         * @return

         */

        public AuthUser login(AuthUser user ) ;

    }

    1. 步骤四:创建AuthService实现类,并通过BCrypt校验密码

    package com.czxy.changgou4.service.impl;

    import com.czxy.changgou4.domain.AuthUser;

    import com.czxy.changgou4.feign.UserFeign;

    import com.czxy.changgou4.service.AuthService;

    import com.czxy.changgou4.utils.BCrypt;

    import org.springframework.stereotype.Service;

    import javax.annotation.Resource;

    /**

     * @author 桐叔

     * @email liangtong@itcast.cn

     */

    @Service

    public class AuthServiceImpl implements AuthService {

        @Resource

        private UserFeign userFeign;

        /**

         * 用户登录

         * @param user

         * @return

         */

        public AuthUser login(AuthUser user ) {

            //远程查询用户

            AuthUser findUser = userFeign.findByUsername(user);

            if(findUser == null) {

                return null;

            }

            //校验密码是否正确

            boolean checkpw = BCrypt.checkpw( user.getPassword(), findUser.getPassword());

            if(checkpw){

                return findUser;

            }

            return null;

        }

    }

    1. 步骤五:创建AuthController,添加login方法
      1. redis中登录验证码和用户输入的验证码进行匹配

    package com.czxy.changgou4.controller;

    /**

     * @author 桐叔

     * @email liangtong@itcast.cn

     */

    import com.czxy.changgou4.domain.AuthUser;

    import com.czxy.changgou4.service.AuthService;

    import com.czxy.changgou4.vo.BaseResult;

    import org.springframework.data.redis.core.StringRedisTemplate;

    import org.springframework.web.bind.annotation.PostMapping;

    import org.springframework.web.bind.annotation.RequestBody;

    import org.springframework.web.bind.annotation.RequestMapping;

    import org.springframework.web.bind.annotation.RestController;

    import javax.annotation.Resource;

    /**

     * Created by liangtong.

     */

    @RestController

    @RequestMapping("/auth")

    public class AuthController {

        @Resource

        private AuthService authService;

        @Resource

        private StringRedisTemplate stringRedisTemplate;

        @PostMapping("/login")

        public BaseResult login(@RequestBody AuthUser user){

            //校验验证码--使用后删除

            String redisCode = stringRedisTemplate.opsForValue().get( "login" + user.getUsername() );

            stringRedisTemplate.delete( "login" + user.getUsername() );

            if(redisCode == null) {

                return BaseResult.error("验证码无效");

            }

            if(! redisCode.equalsIgnoreCase(user.getCode())) {

                return BaseResult.error("验证码错误");

            }

            //登录

            AuthUser loginUser = authService.login(user);

            if(loginUser != null ) {

                return BaseResult.ok("登录成功").append("loginUser",loginUser);

            } else {

                return BaseResult.error("用户名或密码不匹配");

            }

        }

    }

        1. 认证服务:用户登录前端
    1. 步骤一:修改apiclient.js,添加login函数

      //登录

      login : ( user )=> {

        return axios.post('/auth-service/auth/login', user )

      }

    1. 步骤二:修改Login.vue,给验证码绑定变量

     class="checkcode">

                     for="">验证码:

                     type="text"  name="checkcode" v-model="user.code" />

                    

    1. 步骤三:修改Login.vue,给提交按钮绑定事件

  •                  for=""> 

                     type="submit" value="" @click.prevent="loginFn" class="login_btn" />

                  

    1. 步骤四:编写loginFn完成登录功能
      1. 登录成功,跳转到首页
      2. 登录失败,给出提示

        async loginFn() {

          let { data } = await this.$request.login( this.user )

          if( data.code == 20000) {

            //成功

            sessionStorage.setItem('user' , JSON.stringify(data.other.loginUser) )

            //跳转到首页

            this.$router.push('/')

          } else {

            this.errorMsg = data.message

          }

        }

    1. 步骤五:创建首页 ~/pages/index.vue, 

    1. 步骤六:重命名静态页面 ~/static/index.html 为 ~/static/home.html

        1. 修改 TopNav.vue 组件

    1. 完善导航条,根据vuex中的数据,显示不同内容

    1. 步骤一:创建 ~/store/index.js ,并编写vuex内容

    export const state = () => ({

      user: null

    })

    //通用设置

    export const mutations = {

      setData( state , obj) {

        state[obj.key] = obj.value

      }

    }

    1. 步骤二:页面登录成功,将用户信息保存到vuex中

    // 将用户信息保存到vuex中

    this.$store.commit('setData', {key:'user',value: data.data })

    1. 步骤三:修改顶部导航TopNav.vue
      1. 从vuex中的数据

        1. vuex刷新数据丢失
    1. 刷新操作:
      1. 点击刷新按钮
      2. 点击回退按钮
      3. 地址栏直接输入地址
    2. 现象:
      1. vuex在刷新操作后,数据丢失了
    3. 解决方案
      1. 方案1:不是公共组件:页面在pages目录下,可以nuxt.js提供 fetch进行操作。
      2. 方案2:是公共组件:组件在components目录下,借助第三方进行存储(cookie、localStorage、sessionStorage)
        1. 选择1:sessionStorage存放数据,如果vuex中没有,将sessionStorage同步过去。
        2. 选择2:vuex中actions模块就可以发送ajax,从而同步数据。
    4. 具体操作:
      1. 如果vuex中没有数据,使用sessionStorage的数据填充vuex。
      2. 修改TopNav.vue页面

  • 相关阅读:
    神经网络常用激活函数详解
    Rust变量绑定
    Vue源码用到了哪些设计模式
    2022NISCTF--web
    【差旅游记】初见乌海湖
    【教程】在 visual studio 共享和重用项目属性
    R语言使用epiDisplay包的aggregate函数将数值变量基于因子变量拆分为不同的子集,计算每个子集的汇总统计信息
    基于java找到并显示100以内的素数
    阿里P8肝了30天整理的10W字Java面试总结,涵盖26个技术栈,太全了
    vue-rouer 路由
  • 原文地址:https://blog.csdn.net/weixin_45481821/article/details/127501211