几种简单的登录方式的实现——前端+后端

Spring Boot基础学习之(六):前后端交互实现用户登录界面 如何通过前端交互:实现用户登录界面? 阅读详情
AI摘要

本文详细介绍了四种常见的登录方式:普通登录、Token验证、微信登录及手机号登录。每种方式都提供了前后端实现的具体代码示例,涵盖了从前端提交数据到后端处理的全过程。

登录方式的实现

引言

想了一下之前项目中用到的登录方式,简单的总结一下

1、普通登录

  • 普通登录的实现:根据用户输入的用户名和密码,提交到后台,后台判断用户输入的信息是否在数据库中存在,如果存在就给前端返回数据。
  • 出现的问题:只要数据库存在用户信息,不管任何时候都可以登录,所以存在安全问题,就需要考虑权限控制,安全认证,防止CSRF攻击等问题。

前端代码

$.ajax({
            url: '/login',
            type: 'POST',
            dataType: "json",
            data: {
                "username": username,
                "password": password,
            },
            success: function (result1) {
                //获取后台数据result1
                if ("true" === result1.flag) {
                    //信息正确,跳转到首页
                    window.location.href = "/common/index";
                } else if ("false" === result1.flag) {
                    $("#tip2").html("用户不存在!");
                }
            },
            async: true,
            error: function () {
                //请求失败跳转到登录
                window.location.href = "/tologin";
           }
})

后端Controller代码

@RequestMapping("/login")
    @ResponseBody
    public Map<String, String> userLogin(@RequestParam("username") String username,
                                         @RequestParam("password") String password,
                                         HttpServletRequest request) {
        Users users = userService.userLogin(username, password);
        Map<String, String> result = new HashMap<String, String>();
        if (users != null) {
            result.put("flag", "true");
        } else {
            result.put("flag", "false");
        }
        return result;
    }

后端Service代码

public Users userLogin(String username, String password) {
        return usermapper.userLogin(username, password);
 }

2、Token验证

  • 什么是Token

    它是在后台也就是服务端产生的一串字符串,用来给前端鉴权的一种方法,前端如果遇到很频繁的请求后台数据时,每次都需要把当前登录用户信息与数据库的比对,判断是否正确,才返回数据,这样无疑会增加服务器压力

  • Token的作用

    避免CSRF攻击

    Token属于无状态的,可以在多个服务中共享

  • 在项目中的实现:把用户登录信息提交到后台,后台会先判断数据库表中是否有这个人,如果不等于空,就生成Token令牌,把信息传给前端,前端收到Token令牌后,保存到Local Storage,可以弄一个axios的拦截器,每次进行axios请求时,判断一下Local Storage中是否含有Token,保证了登录安全性

前端代码

async success() {
      // 发起登入请求
      const { data: res } = await this.$http.post(
        "api/system/user/login",
        this.userLoginForm
      );
      if (res.success) {
        this.$message({
          title: "登入成功",
          message: "欢迎你进入系统",
          type: "success"
        });
        // 把后台返回的token信息保存到LocalStorage
        LocalStorage.set(LOCAL_KEY_XINGUAN_ACCESS_TOKEN, res.data);
        // 获取当前登录用户用户信息
        await this.getUserInfo();
      } else {
        this.$message.error({
          title: "登入失败",
          message: res.data.errorMsg,
          type: "error"
      });
}

后端Controller代码

    @PostMapping("/login")
public ResponseBean<String> login(@RequestBody UserLoginDTO userLoginDTO, HttpServletRequest request) throws SystemException {
       log.info(userLoginDTO.getUsername()+userLoginDTO.getPassword()+userLoginDTO.getImageCode());
String token=
userService.login(userLoginDTO.getUsername(),userLoginDTO.getPassword(),userLoginDTO.getImageCode());
       loginLogService.add(request);
       return ResponseBean.success(token);
}

后端Service代码

 @Override
    public String login(String username, String password,String code) throws SystemException {
        String token;
        //获取随机验证码
        String verifyCode = (String) redisTemplate.opsForValue().get("imageCode");
        if(code.equals(verifyCode)){
            User user = apiUserService.findUserByName(username);
            if (user != null) {
                //对密码进行加盐加密
                String salt = user.getUSalt();
                //秘钥为盐
                String target = MD5Utils.md5Encryption(password, salt);
                //生成Token
                token = JWTUtils.sign(username, target);
                JWTToken jwtToken = new JWTToken(token);
                try {
                    SecurityUtils.getSubject().login(jwtToken);
                } catch (AuthenticationException e) {
                    throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,e.getMessage());
                }
            } else {
                throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,"用户不存在");
            }
        }else{
            throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,"验证码错误");
        }
        return token;
    }

3、微信登录

微信登录也是一种安全登录方式,它录是基于OAuth 2.0协议标准构建的微信OAuth 2.0授权登录系统,时序图如下

img

官方文档

https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

前端代码

//后台接口
const api_name = `/api/ucenter/wx`
export default {
  getLoginParam() {
    return request({
      url: `${api_name}/getLoginParam`,
      method: `get`
    })
  }
}
weixinApi.getLoginParam().then(response => {
        console.log(response);
        let REDIRECT_URI = encodeURIComponent(response.data.redirectUri);
        var obj = new WxLogin({
          self_redirect: true,
          id: "weixinLogin", // 需要显示的容器id
          appid: response.data.appid, // 公众号appid wx*******
          scope: response.data.scope, // 网页默认即可
          redirect_uri: REDIRECT_URI, // 授权成功后回调的url
          state: response.data.state, // 可设置为简单的随机数加session用来校验
          style: "black", // 提供"black"、"white"可选。二维码的样式
          href: "" // 外部css文件url,需要https
        });
});

后端代码

application.properties文件配置

//微信开发平台appid
wx.open.app_id=
//微信开发平台appsecret
wx.open.app_secret=
//微信开发平台重定向地址
wx.open.redirect_url=
//配置前端域名地址
yygh.baseUrl=


后端Controller代码

//微信扫码
@GetMapping("getLoginParam")
    @ResponseBody
    public Result genQrConnect() {
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("appid", ConstantWxPropertiesUtils.WX_OPEN_APP_ID);
            map.put("scope","snsapi_login");
            String wxOpenRedirectUrl = ConstantWxPropertiesUtils.WX_OPEN_REDIRECT_URL;
            wxOpenRedirectUrl = URLEncoder.encode(wxOpenRedirectUrl, "utf-8");
            map.put("redirect_uri",wxOpenRedirectUrl);
            map.put("state",System.currentTimeMillis()+"");
            return Result.ok(map);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
}


	// 微信扫描后回调的方法
    @GetMapping("callback")
    public String callback(String code,String state) {
        // 第一步 获取临时票据 code
        System.out.println("code:"+code);
        // 第二步 拿着code和微信id和秘钥,请求微信固定地址,得到两个值
        // 使用code和appid以及appscrect换取access_token
        //  %s占位符
        StringBuffer baseAccessTokenUrl = new StringBuffer()
                .append("https://api.weixin.qq.com/sns/oauth2/access_token")
                .append("?appid=%s")
                .append("&secret=%s")
                .append("&code=%s")
                .append("&grant_type=authorization_code");
        String accessTokenUrl = String.format(baseAccessTokenUrl.toString(),
                ConstantWxPropertiesUtils.WX_OPEN_APP_ID,
                ConstantWxPropertiesUtils.WX_OPEN_APP_SECRET,
                code);
        //使用httpclient请求这个地址
        try {
            String accesstokenInfo = HttpClientUtils.get(accessTokenUrl);
            System.out.println("accesstokenInfo:"+accesstokenInfo);
            //从返回字符串获取两个值 openid  和  access_token
            JSONObject jsonObject = JSONObject.parseObject(accesstokenInfo);
            String access_token = jsonObject.getString("access_token");
            String openid = jsonObject.getString("openid");

            // 判断数据库是否存在微信的扫描人信息
            // 根据openid判断
            UserInfo userInfo = userInfoService.selectWxInfoOpenId(openid);
            if(userInfo == null) { // 数据库不存在微信信息
                // 第三步 拿着openid和access_token请求微信地址,得到扫描人信息
                String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
                        "?access_token=%s" +
                        "&openid=%s";
                String userInfoUrl = String.format(baseUserInfoUrl, access_token, openid);
                String resultInfo = HttpClientUtils.get(userInfoUrl);
                System.out.println("resultInfo:"+resultInfo);
                JSONObject resultUserInfoJson = JSONObject.parseObject(resultInfo);
                // 解析用户信息
                // 用户昵称
                String nickname = resultUserInfoJson.getString("nickname");
                // 用户头像
                String headimgurl = resultUserInfoJson.getString("headimgurl");

                // 获取扫描人信息添加数据库
                userInfo = new UserInfo();
                userInfo.setNickName(nickname);
                userInfo.setOpenid(openid);
                userInfo.setStatus(1);
                userInfoService.save(userInfo);
            }
            // 返回name和token字符串
            Map<String,String> map = new HashMap<>();
            String name = userInfo.getName();
            if(StringUtils.isEmpty(name)) {
                name = userInfo.getNickName();
            }
            if(StringUtils.isEmpty(name)) {
                name = userInfo.getPhone();
            }
            map.put("name", name);

            // 判断userInfo是否有手机号,如果手机号为空,返回openid
            // 如果手机号不为空,返回openid值是空字符串
            // 前端判断:如果openid不为空,绑定手机号,如果openid为空,不需要绑定手机号
            if(StringUtils.isEmpty(userInfo.getPhone())) {
                map.put("openid", userInfo.getOpenid());
            } else {
                map.put("openid", "");
            }
            // 使用jwt生成token字符串
            String token = JwtHelper.createToken(userInfo.getId(), name);
            map.put("token", token);
            // 跳转到前端页面
            return "redirect:" + ConstantWxPropertiesUtils.BASE_URL + "/weixin/callback?token="+map.get("token")+ "&openid="+map.get("openid")+"&name="+URLEncoder.encode(map.get("name"),"utf-8");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
}

4、手机号登录

手机号的登录实现:根据用户输入的手机号,当提交登录后,后台会先判断手机号是否会空,如果不为空,利用一个可以生成随机验证码的方法,把验证码保存到Redis中,并设置有效时间,再把配置参数信息包括生成的验证码,提交到阿里云那里,判断配置信息是否正确,如果正确,向用户手机号发送短信验证码,用户输入验证码后,最后把输入的验证码用来与Redis中的验证码对比,如果相同就返回数据给前端

引入依赖

<dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>aliyun-java-sdk-core</artifactId>
</dependency>

application.properties配置

//配置阿里云API的密钥
aliyun.sms.regionId=default
aliyun.sms.accessKeyId=
aliyun.sms.secret=


前端代码

<div class="operate-view" v-if="dialogAtrr.showLoginType === 'phone'">
          <div class="wrapper" style="width: 100%">
            <div class="mobile-wrapper" style="position: static;width: 70%">
              <span class="title">{{ dialogAtrr.labelTips }}</span>
              <el-form>
                <el-form-item>
                  <el-input
                    v-model="dialogAtrr.inputValue"
                    :placeholder="dialogAtrr.placeholder"
                    :maxlength="dialogAtrr.maxlength"
                    class="input v-input"
                  >
                    <span
                      slot="suffix"
                      class="sendText v-link"
                      v-if="dialogAtrr.second > 0"
                    >{{ dialogAtrr.second }}s</span>
                    <span
                      slot="suffix"
                      class="sendText v-link highlight clickable selected"
                      v-if="dialogAtrr.second == 0"
                      @click="getCodeFun()"
                    >重新发送</span>
                  </el-input>
                </el-form-item>
              </el-form>
              <div class="send-button v-button" @click="btnClick()">{{ dialogAtrr.loginBtn }}</div>
            </div>
            <div class="bottom">
              <div class="wechat-wrapper" @click="weixinLogin()">
                <span class="iconfont icon"></span>
              </div>
              <span class="third-text">第三方账号登录</span>
          </div>
      </div>
</div>


//后台接口
const api_name = `/api/sms`
export default {
  sendCode(mobile) {
    return request({
      url: `${api_name}/send/${mobile}`,
      method: `get`
    })
  }
}


	// 获取验证码
    getCodeFun() {
      if (!/^1[34578]\d{9}$/.test(this.userInfo.phone)) {
        this.$message.error("手机号码不正确");
        return;
      }

      // 初始化验证码相关属性
      this.dialogAtrr.inputValue = "";
      this.dialogAtrr.placeholder = "请输入验证码";
      this.dialogAtrr.maxlength = 6;
      this.dialogAtrr.loginBtn = "马上登录";

      // 控制重复发送
      if (!this.dialogAtrr.sending) return;
      // 发送短信验证码
      this.timeDown();
      this.dialogAtrr.sending = false;
      smsApi
        .sendCode(this.userInfo.phone)
        .then(response => {
          this.timeDown();
        })
        .catch(e => {
          this.$message.error("发送失败,重新发送");
          // 发送失败,回到重新获取验证码界面
          this.showLogin();
        });
    },

    // 倒计时
    timeDown() {
      if (this.clearSmsTime) {
        clearInterval(this.clearSmsTime);
      }
      this.dialogAtrr.second = 60;
      this.dialogAtrr.labelTips = "验证码已发送至" + this.userInfo.phone;
      this.clearSmsTime = setInterval(() => {
        --this.dialogAtrr.second;
        if (this.dialogAtrr.second < 1) {
          clearInterval(this.clearSmsTime);
          this.dialogAtrr.sending = true;
          this.dialogAtrr.second = 0;
        }
      }, 1000);
    },

后端Controller代码

	// 用户手机号登录接口
    @PostMapping("login")
    public Result login(@RequestBody LoginVo loginVo) {
        Map<String,Object> info = userInfoService.loginUser(loginVo);
        return Result.ok(info);
   }

	// 发送手机验证码
    @GetMapping("send/{phone}")
    public Result sendCode(@PathVariable String phone) {
        //从redis获取验证码,如果获取获取到,返回ok
        // key 手机号  value 验证码
        String code = redisTemplate.opsForValue().get(phone);
        if(!StringUtils.isEmpty(code)) {
            return Result.ok();
        }
        //如果从redis获取不到,
        // 生成验证码,
        code = RandomUtil.getSixBitRandom();
        //调用service方法,通过整合短信服务进行发送
        boolean isSend = msmService.send(phone,code);
        //生成验证码放到redis里面,设置有效时间
        if(isSend) {
            redisTemplate.opsForValue().set(phone,code,1, TimeUnit.MINUTES);
            return Result.ok();
        } else {
            return Result.fail().message("发送短信失败");
        }
    }

后端Service代码

	// 手机号登录service
	@Override
    public Map<String, Object> loginUser(LoginVo loginVo) {
        //从loginVo获取输入的手机号,和验证码
        String phone = loginVo.getPhone();
        String code = loginVo.getCode();

        //判断手机号和验证码是否为空
        if(StringUtils.isEmpty(phone) || StringUtils.isEmpty(code)) {
            throw new Exception(ResultCodeEnum.PARAM_ERROR);
        }

        //判断手机验证码和输入的验证码是否一致
        String redisCode = redisTemplate.opsForValue().get(phone);
        if(!code.equals(redisCode)) {
            throw new Exception(ResultCodeEnum.CODE_ERROR);
        }

        //绑定手机号码
        UserInfo userInfo = null;
        if(!StringUtils.isEmpty(loginVo.getOpenid())) {
            userInfo = this.selectWxInfoOpenId(loginVo.getOpenid());
            if(null != userInfo) {
                userInfo.setPhone(loginVo.getPhone());
                this.updateById(userInfo);
            } else {
                throw new Exception(ResultCodeEnum.DATA_ERROR);
            }
        }

        //如果userinfo为空,进行正常手机登录
        if(userInfo == null) {
            //判断是否第一次登录:根据手机号查询数据库,如果不存在相同手机号就是第一次登录
            QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
            wrapper.eq("phone",phone);
            userInfo = baseMapper.selectOne(wrapper);
            if(userInfo == null) { //第一次使用这个手机号登录
                //添加信息到数据库
                userInfo = new UserInfo();
                userInfo.setName("");
                userInfo.setPhone(phone);
                userInfo.setStatus(1);
                baseMapper.insert(userInfo);
            }
        }

        //校验是否被禁用
        if(userInfo.getStatus() == 0) {
            throw new Exception(ResultCodeEnum.LOGIN_DISABLED_ERROR);
        }

        //不是第一次,直接登录
        //返回登录信息
        //返回登录用户名
        //返回token信息
        Map<String, Object> map = new HashMap<>();
        String name = userInfo.getName();
        if(StringUtils.isEmpty(name)) {
            name = userInfo.getNickName();
        }
        if(StringUtils.isEmpty(name)) {
            name = userInfo.getPhone();
        }
        map.put("name",name);

        //jwt生成token字符串
        String token = JwtHelper.createToken(userInfo.getId(), name);
        map.put("token",token);
        return map;
    }

	//提交验证码
	@Override
    public boolean send(String phone, String code) {
        //判断手机号是否为空
        if(StringUtils.isEmpty(phone)) {
            return false;
        }
        //整合阿里云短信服务
        //设置相关参数
        DefaultProfile profile = DefaultProfile.
                getProfile(ConstantPropertiesUtils.REGION_Id,
                        ConstantPropertiesUtils.ACCESS_KEY_ID,
                        ConstantPropertiesUtils.SECRECT);
        IAcsClient client = new DefaultAcsClient(profile);
        CommonRequest request = new CommonRequest();
        //request.setProtocol(ProtocolType.HTTPS);
        request.setMethod(MethodType.POST);
        request.setDomain("dysmsapi.aliyuncs.com");
        request.setVersion("2017-05-25");
        request.setAction("SendSms");

        //手机号
        request.putQueryParameter("PhoneNumbers", phone);
        //签名名称
        request.putQueryParameter("SignName", "****");
        //模板code
        request.putQueryParameter("TemplateCode", "******");

        request.putQueryParameter("TemplateCode", "*****");
        //验证码  使用json格式   {"code":"123456"}
        Map<String,Object> param = new HashMap();
        param.put("code",code);
        request.putQueryParameter("TemplateParam", JSONObject.toJSONString(param));

        //调用方法进行短信发送
        try {
            CommonResponse response = client.getCommonResponse(request);
            System.out.println(response.getData());
            return response.getHttpResponse().isSuccess();
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public boolean send(MsmVo msmVo) {
        if(!StringUtils.isEmpty(msmVo.getPhone())) {
            boolean isSend = this.send(msmVo.getPhone(), msmVo.getParam());
            return isSend;
        }
        return false;
}

@Data
@ApiModel(description = "短信实体")
public class MsmVo {

    @ApiModelProperty(value = "phone")
    private String phone;

    @ApiModelProperty(value = "短信模板code")
    private String templateCode;

    @ApiModelProperty(value = "短信模板参数")
    private Map<String,Object> param;
}

一步步使用SpringBoot结合Vue实现登录和用户管理功能,携程 前端面试 按照官方文档,来进行MP的分页。作为Mybatis的增强工具,MP自然是支持自定义sql的。其实在MP中,单表操作基本上是不用自己写sql。这里只是为了演示MP的自定义sql,毕竟在实际应用中,批量操作、多表操作还是更适合自定义sql实现。修改pom.xml,在 中添加:**/*.xmltrue配置文件:在application.properties中添加mapper扫描路径及实体类别名包阿里十分注重你对源码的理解,对你所学,所用东西的理解,对项目的理解。一个人可以走的很快,但一群人才能走的更远。 阅读详情

相关推荐

总结 前后端分离 springboot+shiro登录验证的几种方式

总结 前后端分离 springboot+shiro登录验证的几种方式登录验证硬编码方式(不推荐)在自定义过滤器中返回给前端错误码设置shiro的loginURL使用注解方式(推荐)权限控制使用注解方式 登录验证 在前后端的登录验证中,如果当前用户未登录要返回给前端一个状态码。返回给前端状态码有以下几种方式(暂时只知道这些) 硬编码方式(不推荐) 在获取当前登录者id时判断是否已经登录,如果没有登录就抛出自定义异常,通过全局异常捕获返回给前端固定的状态码 public Long getLoginID() {

werewolf2的博客 1440

前端常见登录实现方案 + 单点登录方案

登录是每个网站中都会用到的一个必备功能,但是如何实现一个优秀的登录功能,如何根据自己的项目来选择一个适合自己的登录方案?今天我们就来介绍几种常用的登录方案。 Cookie + Session 登录 Token 登录 SSO 单点登录 OAuth 第三方登录 一、Cookie + Session 登录 HTTP 是一种无状态的协议,客户端每次发送请求时,首先要和服务器端建立一个连接,在请求完成后又会断开这个连接。这种方式可以节省传输时占用的连接资源,但同时也存在一个问题:每次请求都是独立的,服务器端无法

XH_jing的博客 1万+

前端做登录验证码功能的理解

前言 前端小白一名,记录日常学习生活点滴【第二周】 一、关于 前端做登录验证码功能的个人理解 做这个功能之前一定要搞清楚它的作用是什么: 【用它来确定正在访问网站的用户是人而不是一个程序】 原因:不管是何种验证码方式,都是要让程序难以判断,而让人好判断的原则设计的。 【防止用户利用机器人自动注册、登录、灌水】 原因:安全角度出发,随着网络速度的提高,如果没有一种防御机制的话,那么攻击者完全可以通过疯狂猜测尝试来获得用户的密码,还可以利用机器人自动注册、登录、灌水。想想多可怕。 一般来说,前端做登录验证就大

m0_48940868的博客 2909

登录功能的实现(包括前后端)

登录功能对于前端刚入门不久的我来说较为困难,花了很久查阅了许多资料。代码部分涉及的技术栈和细节也很多。过了一段时间来看,发现对自己写的代码竟然感觉十分陌生,故想写篇博客,对整个过程进行梳理。方便自己重看代码,同时也希望能帮到在实现这一功能受阻的程序猿们o( ̄▽ ̄)ブ前端验证用户输入是否符合规范前端调用后端登录接口,向后端发起登录请求后端收到请求,查验数据库种是否有相应账号以及密码是否正确验证通过后,将成功信息连同token一起发送给前端。...................................

_Kiwi_berry的博客 3万+

Rsoft仿真实战:长周期光纤光栅参数优化与模式耦合分析

本文详细介绍了使用Rsoft软件进行长周期光纤光栅(LPFG)参数优化与模式耦合分析的实战方法。通过Rsoft仿真,可以高效优化光栅周期、包层厚度等关键参数,深入分析纤芯模与包层模的耦合特性,为光纤通信和传感应用提供可靠的设计依据。

h0i1j2k3l的博客 1115

别再让电池充不满!用CN3791芯片设计太阳能充电电路,这几个调试坑我帮你踩了

本文详细解析了使用CN3791芯片设计太阳能充电电路时的常见调试问题及解决方案。从RCS电阻的选择到MPPT电压偏差的修正,再到线路损耗和温度补偿的优化,提供了全面的避坑指南。通过实测数据和优化方案,帮助工程师提升锂电池充电效率,确保太阳能充电电路的稳定性和可靠性。

weixin_42528191的博客 238

四种常见的登录方案

1.Cookie + Session 登录 HTTP 是一种无状态的协议,客户端每次发送请求时,首先要和服务器端建立一个连接,在请求完成后又会断开这个连接。这种方式可以节省传输时占用的连接资源,但同时也存在一个问题:每次请求都是独立的,服务器端无法判断本次请求和上一次请求是否来自同一个用户,进而也就无法判断用户的登录状态。 为了解决 HTTP 无状态的问题,Lou Montulli 在 1994 年的时候,推出了 Cookie。 Cookie 是服务器端发送给客户端的一段特殊信息,这些信息以文本的方式存放在

Carol的小星球 1万+

AD936x Evaluation Software 详细配置

作者:ShownSun 工作室:时沿科技 文章目录AD936x Evaluation Software详细配置1 系统概述2 AD9361 Wireless Transceiver Evaluation Setup2.1 标签描述2.2 用户参数2.3详细配置3 AD936x RF Wizard3.1 标签描述3.2 用户参数3.3 详细配置4 AD936x Digital Filter Wizard4.1 标签描述4.1.1 时钟配置4.1.2 滤波器配置4.1.3 接收滤波器配置4.1.4 发射滤..

ShownSun博客 5190

前端登录方案?这一篇就够了

登录是每个网站中都经常用到的一个功能,在页面上我们输入账号密码,敲一下回车键,就登录了,但这背后的登录原理你是否清楚呢?今天我们就来介绍几种常用的登录方式。Cookie + Sessio...

小生方勤 974

Cadence Allegro实战:如何精准导入结构DXF文件避免安装偏差(附图层配置技巧)

本文详细讲解了在Cadence Allegro中精准导入结构DXF文件以避免安装偏差的实战技巧。核心在于导入前的单位校准、创建专用图层结构,以及基于坐标基准点的精确对齐方法。文章还分享了将DXF图形转化为正式板框和禁布区、高效管理图层以及向结构工程师导出DXF的完整流程,帮助PCB工程师确保设计与机械结构完美契合。

1a2s3d4f5g的博客 506

RandLA-Net复现SemanticKITTI和S3DIS数据集

RandLA-Net复现KITTI和室内数据集

weixin_48845174的博客 4109

spring MVC框架下前台往java后台传送json数据

前台页面 用户名 密 码 JavaScript中的方法: 方式一: function loginSubmit(){ $.ajax({ type: "POST", url: "***/login", data:{

Wendz的博客 3004

ESP32设备驱动-TB6612FNG直流电机驱动

TB6612FNG 是一款出色的双电机驱动器,非常适合将两个小型直流电机(例如微型金属齿轮电机)连接到微控制器,它还可以用于控制单个双极步进电机。 基于 MOSFET 的 H 桥比 L298N 和 Sanyo 的 LB1836M 等旧式驱动器中使用的基于 BJT 的 H 桥效率高得多,后者允许将更多电流输送到电机,而从逻辑电源汲取的电流更少 (对于真正低电压的应用,LB1836 仍然具有 TB6612 的优势)。

视觉与物联智能 3401

前端如何调用后端接口?有哪几种方式?

一般来讲,前端不会给后端接口,而是后端给前端接口的情况比较普遍。一些人可能不理解接口和前端开发的关系,其实不合适的接口设计会极大地影响用户的页面体验。那么今天就跟着我一起来看看,前端如何调用后端接口?有哪几种方式? 首先,要弄清楚前端提供一个接口或者调用后台接口,那么这个接口具体指什么?网上用户上传图片作为头像这个需求需要后台人员处理,当用户登录 修改自己个人信息的时候,上传了头像。此时,后台处...

xiaoxijing的博客 5万+

Dify使用教程3:Dify创建工作流

Dify使用教程3:Dify创建工作流 接着,我们连接下一个节点:“LLM”填入上下文变量为:result。这时候知识库就添加成功了。添加新节点:结束节点。

拥抱具身智能,昇腾Ascend C 5128

嵌入式铁头山羊stm32:一文总结

本文是一篇STM32嵌入式开发的综合知识总结,涵盖了STM32基础概念、GPIO、通信协议、外设驱动等核心内容。文章首先介绍了STM32的基本概念和型号含义,然后详细讲解了GPIO的8种工作模式及实验案例。接着重点阐述了USART、I2C、SPI三种通信协议的原理和实现方法,包括硬件连接、编程接口和实验应用。此外还介绍了OLED显示原理、中断系统、定时器、ADC转换等关键技术,每个模块都配有对应的实验案例和代码实现参考。文章内容全面系统,既包含理论知识,又提供实践指导,适合作为STM32开发的快速参考手册。

古泽汉书的博客 2782

前后端交互的几种方式

Vue+Springboot 前后端交互的几种方式 前置知识点 用于接收前端参数传递的几个注解 @RequestBody注解 @RequestParam注解 @PathVariable注解 @RequestParam和@PathVariable的区别 @RequestBody的使用 这两篇博客写的非常的详细,看完就会了 什么是Json格式, 前后端交互主要有Json格式、form-date格式等,Json格式为主。 { "ID": 1001, "name": "张三", "age

weixin_46173995的博客 1万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

前端常用登录方式

5种常用登录方式

zhenshu_guo的博客 2008

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Vue + Spring Boot 项目实战(六):前端路由与登录拦截器

前端路由的基本原理、使用 history 路由模式时后端登录拦截器的配置、Vuex 的引入以及前端拦截器的实现。

Evan 的博客 12万+

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

springboot整合前端实现简单的登录注册

本demo接续上边项目整合web,实现一个简单的web端注册登录 1、首先给dao层加数据库操作: 登录需要一个select查询,查找用户名密码和用户输入的是否匹配。 注册需要一个insert into插入,把新增的数据插入到数据库表。 在UserMapper.java和UserMapper.xml添加如下 2、然后在UserService.java和UserServiceImpl添加对dao层的调用。 3、最后在control...

qq:458510729的博客 1466

html请求的几种方式,前端如何调用后端接口?有哪几种方式?

一般来讲,前端不会给后端接口,而是后端给前端接口的情况比较普遍。一些人可能不理解接口和前端开发的关系,其实不合适的接口设计会极大地影响用户的页面体验。那么今天我们就来看看,前端如何调用后端接口?有哪几种方式?首先,要弄清楚前端提供一个接口或者调用后台接口,那么这个接口具体指什么?网上用户上传图片作为头像 这个需求需要后台人员处理,当用户登录 修改自己个人信息的时候,上传了头像。此时,后台处理该用户...

weixin_39936792的博客 9504

前端后端交互请求的几种方式

1. GET:获取资源,请求参数在URL中传递,一般用于数据查询操作。 2. POST:提交数据,请求参数在请求体中传递,一般用于数据新增和修改操作。 3. PUT:更新数据,请求参数在请求体中传递,一般用于数据更新操作。 4. DELETE:删除数据,请求参数在URL中传递,一般用于数据删除操作。

qq_56921846的博客 2067

springboot实现几种常见登录(注册)方式

短信验证码注册、微信扫码登录

少年Dream 1万+

前后端分离登录

1.http无协议 因为HTTP是无状态的协议,也就是说,这个协议是无法记录用户访问状态的,其每次请求都是独立的无关联的,一笔是一笔。而我们的网站都是设计成多个页面的,所在页面跳转过程中我们需要知道用户的状态,尤其是用户登录的状态,这样我们在页面跳转后我们才知道是否可以让用户有权限来操作一些功能或是查看一些数据。 所以,我们每个页面都需要对用户的身份进行认证。为了实现这一功能,用得最多的技术就是浏览器的cookie,我们会把用户登录的信息存放在客户端的cookie里,这样,我们每个页面都从这个cookie里

m0_51279688的博客 4229
上一篇: Vue2.x中父子组件通信
下一篇: Windows下Arthas的安装和卸载
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值