B072-项目实战-用户模块--前台登录 三方登录

目录

      • 前台登录-账号登录
        • 前端完成
        • 左上角显示用户信息
        • 配置前置拦截器、后置拦截器和不受限资源拦截器
      • 三方登录-微信登录
        • 概述
        • 流程图
        • 用法
        • 代码实现步骤分析:
        • 实现准备
        • 代码
          • 前端
            • login.html
            • callback.html
          • 后端
            • LoginController-微信登录
            • LoginServiceImpl-微信登录
            • 解决回调域名不能跨域
            • 绑定页面准备
            • 改造发短信验证码接口
            • LoginController-绑定微信用户
            • LoginServiceImpl-绑定微信用户

前台登录-账号登录

前端完成

1)后台登录接口(和管理员登录接口共用,以type划分)
2)前台登录实现并且保存loginInfo和token到localStorage,登录成功跳转首页,并展示用户名
3)前台通过axios的前置拦截器携带token到后台
4)后台做token的登录拦截器,如果没有回报错给前台(前面已写,共用)
5)前台通过axios后置拦截器对后台登录拦截错误进行跳转到登录页面
6)前台也要做拦截-有的地址是不需要访问后台

login.html中引入axios和vue
标签 - data - 按钮 - methods

localstorage与域名挂钩,同一个域名下的key只能存在一个,不同域名下的key名称可以一样,即前后台的token名称可以一样

login.html

<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>登录</title>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport"
          content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta name="format-detection" content="telephone=no">
    <meta name="renderer" content="webkit">
    <meta http-equiv="Cache-Control" content="no-siteapp"/>

    <link rel="stylesheet" href="./AmazeUI-2.4.2/assets/css/amazeui.css"/>
    <link href="./css/dlstyle.css" rel="stylesheet" type="text/css">
    <!--引入vue和axios-->
    <script src="js/plugin/vue/dist/vue.min.js"></script>
    <script src="js/plugin/axios/dist/axios.js"></script>
    <!--全局使用-->
    <script src="js/common.js"></script>
</head>
<body>
<div class="login-boxtitle">
    <a href="home.html"><img alt="logo" src="./images/logobig.png"/></a>
</div>
<div class="login-banner">
    <div class="login-main">
        <div class="login-banner-bg"><span></span><img src="./images/big.jpg"/></div>
        <div class="login-box">
            <h3 class="title">登录商城</h3>
            <div class="clear"></div>
            <div class="login-form">
                <form>
                    <div class="user-name">
                        <label for="user"><i class="am-icon-user"></i></label>
                        <input type="text" name="" v-model="userLoginForm.username" id="user" placeholder="邮箱/手机/用户名">
                    </div>
                    <div class="user-pass">
                        <label for="password"><i class="am-icon-lock"></i></label>
                        <input type="password" name="" v-model="userLoginForm.password" id="password"
                               placeholder="请输入密码">
                    </div>
                </form>
            </div>
            <div class="login-links">
                <label for="remember-me"><input id="remember-me" type="checkbox">记住密码</label>
                <a href="#" class="am-fr">忘记密码</a>
                <a href="register.html" class="zcnext am-fr am-btn-default">注册</a>
                <br/>
            </div>
            <div class="am-cf">
                <input type="button" @click="login" name="" value="登 录" class="am-btn am-btn-primary am-btn-sm">
            </div>
            <div class="partner">
                <h3>合作账号</h3>
                <div class="am-btn-group">
                    <li><a href="#"><i class="am-icon-qq am-icon-sm"></i><span>QQ登录</span></a></li>
                    <li><a href="#"><i class="am-icon-weibo am-icon-sm"></i><span>微博登录</span> </a></li>
                    <li><a href="#"><i class="am-icon-weixin am-icon-sm"></i><span>微信登录</span> </a></li>
                </div>
            </div>
        </div>
    </div>
</div>
<div class="footer ">
    <div class="footer-hd ">
        <p>
            <a href="# ">恒望科技</a>
            <b>|</b>
            <a href="# ">商城首页</a>
            <b>|</b>
            <a href="# ">支付宝</a>
            <b>|</b>
            <a href="# ">物流</a>
        </p>
    </div>
    <div class="footer-bd ">
        <p>
            <a href="# ">关于恒望</a>
            <a href="# ">合作伙伴</a>
            <a href="# ">联系我们</a>
            <a href="# ">网站地图</a>
            <em>© 2015-2025 Hengwang.com 版权所有. 更多模板 <a href="http://www.cssmoban.com/" target="_blank"
                                                       title="模板之家">模板之家</a> - Collect from <a
                    href="http://www.cssmoban.com/" title="网页模板" target="_blank">网页模板</a></em>
        </p>
    </div>
</div>
</body>
<script type="text/javascript">
    new Vue({
        el: ".login-main",
        data: {
            userLoginForm: {
                username: "",
                password: "",
                type: 1
            }
        },
        methods: {
            login() {
                this.$http.post("/login/account", this.userLoginForm)
                    .then(result => {
                        result = result.data;
                        if (result.success) {
                            //保存信息到localstorage
                            var resultObj = result.resultObj;
                            localStorage.setItem("token", resultObj.token);	//不同域名下的key名称可以一样
                            localStorage.setItem("logininfo", JSON.stringify(resultObj.logininfo));
                            alert("登录成功!");
                            //提示登录成功
                            //跳转到主页
                            location.href = "/index.html";
                        } else {
                            alert(result.message);
                        }
                    })
                    .catch(result => {
                        alert("系统异常!");
                    })
            }
        },
        mounted() {
        }
    })
</script>
</html>

左上角显示用户信息

index.html
引入vue和axios
页面元素 - vue实例 -

<!--引入vue和axios-->
<script src="js/plugin/vue/dist/vue.min.js"></script>
<script src="js/plugin/axios/dist/axios.js"></script>
<!--全局使用-->
<script src="js/common.js"></script>
<div id="myDiv">
	<div class="menu-hd" v-if="logininfo">
		<a href="#" target="_top" class="h">
			欢迎您:<span style="color: red">{{logininfo.username || logininfo.phone || logininfo.email ||''}}</span>
		</a>
	</div>
	<div class="menu-hd" v-else>
		<a href="#" target="_top" class="h">亲,请登录</a>
		<a href="register.html" target="_blank">免费注册</a>
	</div>
		<script type="text/javascript">
			new Vue({
				el:"#myDiv",
				data:{
					logininfo:null
				},
				mounted(){
					let loginObjStr =  localStorage.getItem("logininfo");
					if(loginObjStr){
						this.logininfo = JSON.parse(loginObjStr);
					}
				}
			})
		</script>

配置前置拦截器、后置拦截器和不受限资源拦截器

common.js

//配置axios的全局基本路径
/*axios.defaults.baseURL='/api' 前端解决跨域*/
axios.defaults.baseURL='http://localhost:8080/'

/**
 * 使用前提,要发送axios的页面,都应该要引入common.js
 * axios前置拦截器:作用:每次发送axios请求,需要携带token给后端
 */
axios.interceptors.request.use(config=>{
    //携带token
    let uToken =  localStorage.getItem("token");
    if(uToken){
        config.headers['token']=uToken;
    }
    return config;//一定要返回配置
},error => {
    Promise.reject(error);
})

/**
 * axios后置拦截:作用:后端ajax请求 报错,在这里处理
 */
axios.interceptors.response.use(result=>{
    let data = result.data;
    if(!data.success && data.message==="noLogin"){
        localStorage.removeItem('token');
        localStorage.removeItem('logininfo');
        /*router.push({ path: '/login' });*/
        location.href = "/login.html";
    }
    return result;
},error => {
    Promise.reject(error);
})

//全局属性配置,在任意组件内可以使用this.$http获取axios对象
Vue.prototype.$http = axios

/*js拦截*/
let uri = location.href;//http://127.0.0.1/index.html
/*不是这两个结尾的请求地址,我应该阻止,并校验是否登录*/
if(uri.indexOf("/login.html") == -1 && uri.indexOf("/register.html")==-1
    && uri.indexOf("/index.html") == -1){
    let loginObj = localStorage.getItem('logininfo');
    if(!loginObj){
        location.href = "/login.html";
    }
}

三方登录-微信登录

概述

用户通过微信登录链接访问微信平台
微信返回登录二维码
用户扫码进入微信平台
微信校验用户后返回链接+校验码给本平台 ------- 返回页面信息
本平台通过校验码去微信获取用户信息token ------- 解析页面信息绑定数据,通过校验码去微信获取用户信息token,通过token去微信拿用户信息保存到本平台,设置默认用户密码,下次再扫码校验是微信的和用户是存在的就登录成功

流程图

在这里插入图片描述
在这里插入图片描述

用法

https://open.weixin.qq.com/:注册为开发者
-> 网站应用开发 - 填写信息 - 邮箱激活 - 完善开发者资料 -
开发者认证 - 人工审核,自己无法申请成功,用源码提供的
APPID:wxd853562a0548a7d0,SECRET:4a5d5615f93f24bdba2ba8534642dbb6,回调域:bugtracker.itsource.cn

目前回调域名没有对外,我们是127.0.0.1,要让外网微信能访问到内网地址,
回调域相当于宠物平台的后端地址
开发阶段通过本地hosts解析将回调域名指向本机127.0.0.1

代码实现步骤分析:

在这里插入图片描述
在这里插入图片描述

微信扫码登录具体实现步骤:
1.用户点击主站微信登录A标签按钮,平台带上 appid 和 回调页面地址 发送请求到微信平台,
0.微信端会弹出二维码扫码界面给用户
1.用户扫码后,微信平台获得授权生成http://bugtracker.itsource.cn/callback.html?code=xxxxx,回调到平台callback页面
2.平台callback页面页面加载解析地址栏中的code,携带code和binder.html发送微信登录请求到后端,后端通过APPID,SECRET和code到微信平台获取token和授权用户唯一标识openid

再根据openid看用户是否在本地是否存有WxUser信息和绑定用户User_id
如果有,通过绑定的User_id查询到登录信息,生成token和logininfo返回前端  --->免密登录
 
3.如果没有,返回binderUrl+token+openId给前端,前端跳转到绑定页面,页面加载解析token和openId,填写手机号与短信验证码后带上token和openId发送绑定请求到后端,后端完成验证码验证后携带token和openid发送请求到微信平台拿用户微信信息

然后根据手机号和类型看是否存在此平台登录用户,存在就查出user结合wxUserStr直接保存和绑定进wxUser表,--->然后免密登录
不存在就根据phone和type生成logininfo(密码默认)和拷贝user保存,然后user结合wxUserStr保存和绑定进wxUser表,--->然后免密登录

tips:后面生成logininfo设置默认密码时可以发短信告知用户
项目中该怎么干?
  1.用户点击前端微信按钮
  2.web发起获取授权请求到微信,带上回调地址callback.html
  3.微信展示二维码给用户,让用户扫码
  4.用户扫码后,跳转到我们的callBack页面,会加上一个授权码code给到我们
  5.那么我们在mounted中可以发起微信登录请求到我们的pethome后台,
       传递一个绑定用户信息的地址过来
  6.后台接口中直接获取code,然后发起获取token的请求
     得到token我们是不是又可以发起获取微信用户信息的请求
  7.得到用户后,判断微信用户在我们系统中有没有对应的t_user
     如果有,实现免密登录
     如果没有,弹出一个绑定用户账号信息的窗口,让他完成信息绑定(相当于给他注册一个账号)
     然后在登录成功

实现准备

见文档

代码

前端
login.html
<li><a href="https://open.weixin.qq.com/connect/qrconnect?
			appid=wxd853562a0548a7d0&
			redirect_uri=http://bugtracker.itsource.cn/callback.html&
			response_type=code&
			scope=snsapi_login&
			state=1#
			wechat_redirect ">
	<i class="am-icon-weixin am-icon-sm"></i><span>微信登录</span> </a></li>

拷贝callback页面到web根目录,修改vue和axios引入路径,js拦截放行callback页面,common.js下面补充parseUrlParams2Obj方法

callback.html
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>回调</title>
    <!--引入vue和axios-->
    <script src="js/plugin/vue/dist/vue.min.js"></script>
    <script src="js/plugin/axios/dist/axios.js"></script>
    <!--全局使用-->
    <script src="js/common.js"></script>
</head>
<body>
    <div id="myDiv">
    </div>
<script type="text/javascript">
    new Vue({
        el:"#myDiv",
        mounted(){
            //解析参数上
            let url = location.href;
            let paramObj = parseUrlParams2Obj(url);
            let binderUrl="http://bugtracker.itsource.cn/binder.html";
            //封装请求参数
            let param = {"code":paramObj.code,"binderUrl":binderUrl};
            //发送微信登录验证  到pethome后端
            this.$http.post("/login/wechat",param)
                .then(result=>{
                    result = result.data;
                    if(result.success){//已经绑定,免密登录成功
                        alert("登录成功");
                        //1.将token和登录信息存入localStorage
                        let {token,loginInfo} = result.resultObj;
                        localStorage.setItem("token",token);
                        localStorage.setItem("loginInfo",JSON.stringify(loginInfo));
                        //2.跳转到首页,并显示登录信息
                        location.href="index.html";
                    }else{
                        let url = result.resultObj;
                        //没有绑定,跳转到绑定页面
                        location.href=url;
                    }
                })
                .catch(result=>{
                    alert("系统异常!");
                })
        }
    })
</script>
</body>
</html>
后端
LoginController-微信登录
    /**
     * 微信扫码登录
     * @param params  code  binderUrl
     * @return
     */
    @PostMapping("/wechat")
    public AjaxResult wechat(@RequestBody Map<String,String> params){
        try {
            return loginService.wechat(params);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.me().setMessage("系统繁忙,稍后重试!");
        }
    }
LoginServiceImpl-微信登录
    /**
     * 空校验
     * 通过code去微信平台拿token  同时返回openid
     * 校验是否微信用户和我们平台yoghurt绑定
     * 如果绑定了, 直接免密登录成功
     * 如果没有绑定
     *   跳转到绑定用户信息页面?后端能跳转吗?json {success:false,binderUrl:....}
     */
    @Override
    public AjaxResult wechat(Map<String, String> params) {
        //1.获取参数
        String code = params.get("code");
        String binderUrl = params.get("binderUrl");
        if (StringUtils.isEmpty(code) || StringUtils.isEmpty(binderUrl)) {
            return AjaxResult.me().setMessage("必要参数为空,登录失败");
        }
        //2.发送http请求去微信平台拿token
        String accessTokenUrl = WxConstants.GET_ACK_URL
                .replace("APPID", WxConstants.APPID)
                .replace("SECRET", WxConstants.SECRET)
                .replace("CODE", code);
        String strObj = HttpClientUtils.httpGet(accessTokenUrl);
        System.out.println(strObj);
        JSONObject object = JSONObject.parseObject(strObj);
        String accessToken = (String) object.get("access_token");
        String openId = (String) object.get("openid");
        //3.判断是否绑定微信用户  通过openId 查询微信用户信息,如果查询到了并且有userid
        WxUser wxUser = wxUserMapper.loadByOpenId(openId);
        //  3.1 如果查询到值,并且绑定了数据,直接免密登录
        if (wxUser != null && wxUser.getUser_id() != null) {//免密登录
            // 2.1 如果密码相等  登录成功  存redis,封装返回值
            /**
             * 这里的redis  key就是前端需要存储的token
             */
            //通过用户ID查询到登录人
            Logininfo logininfo = logininfoMapper.loadbyUserId(wxUser.getUser_id());
            String token = UUID.randomUUID().toString();
            redisTemplate.opsForValue().set(token, logininfo, 30, TimeUnit.MINUTES);
            Map<String, Object> map = new HashMap<>();
            map.put("token", token);
            //作为一个高级技师 我们不能将账号和密码传给前端,应该过滤掉
            logininfo.setUsername(null);
            logininfo.setPassword(null);
            map.put("logininfo", logininfo);
            return AjaxResult.me().setResultObj(map);//免密登录成功返回

        } else {// 3.2 如果没有查询那么应该跳转到绑定页面
            String resultUrl = binderUrl + "?accessToken=" + accessToken + "&openId=" + openId;
            return AjaxResult.me().setSuccess(false).setResultObj(resultUrl);//免密登录成功返回
        }
    }
解决回调域名不能跨域

GlobalCorsConfig

config.addAllowedOrigin("http://bugtracker.itsource.cn");
config.addAllowedOrigin("http://bugtracker.itsource.cn:80");
绑定页面准备

拷贝binder.html到web根目录,调整引入路径,调整参数名,js拦截放行

改造发短信验证码接口

见代码

LoginController-绑定微信用户

在这里插入图片描述
在这里插入图片描述

    /**
     * 绑定微信用户接口
     */
    @PostMapping("/binder/wechat")
    public AjaxResult binder(@RequestBody Map<String,String> params){
        try {
            return loginService.binder(params);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.me().setMessage("系统繁忙,稍后重试!");
        }
    }
LoginServiceImpl-绑定微信用户
    @Override
    public AjaxResult binder(Map<String, String> params) {
        String phone  = params.get("phone");
        String accessToken  = params.get("accessToken");
        String openId  = params.get("openId");
        String verifyCode  = params.get("verifyCode");
        //1.空校验
        if(StringUtils.isEmpty(phone) || StringUtils.isEmpty(accessToken) || StringUtils.isEmpty(openId) || StringUtils.isEmpty(verifyCode)){
            return AjaxResult.me().setMessage("必要参数为空,绑定失败");
        }
        //2.验证码是否过期或正确
        Object codeObj = redisTemplate.opsForValue().get(UserConstant.USER_BINDING_CODE+":"+phone);
        //  2.1 验证码是否过期
        if(codeObj == null){
            return AjaxResult.me().setMessage("验证码已经过期,请重新发送验证码!");
        }
        String code = ((String)codeObj).split(":")[0];
        //  2.2 验证码是否正确
        if(!verifyCode.equalsIgnoreCase(code)){
            return AjaxResult.me().setMessage("请输入正确的验证码!");
        }

        //3.查询微信平台用户
        //发送http请求去微信平台拿微信用户
        String userUrl = WxConstants.GET_USER_URL
                .replace("ACCESS_TOKEN", accessToken)
                .replace("OPENID", openId);
        String strObj = HttpClientUtils.httpGet(userUrl);
        System.out.println(strObj);
        if(strObj == null){//拿不到微信用户了
            return AjaxResult.me().setMessage("微信用户不存在!");
        }

        UserDto dto = new UserDto();
        dto.setPhone(phone);
        dto.setType(1);
        //4.查询平台用户是否存在
        Logininfo logininfo = logininfoMapper.loadByDto(dto);
        User user = null;
        if(logininfo != null){//存在平台用户,那么曾经这个手机号已经注册过,直接绑定就可以了
            user = userMapper.loadByloginInfoId(logininfo.getId());
        }else{//平台不存在手机相关的用户
            logininfo = createLoginInfo(phone);
            user = loginInfo2User(logininfo);
            logininfoMapper.save(logininfo);
            user.setInfo(logininfo);
            userMapper.save(user);
        }

        //5.绑定微信用户
        WxUser wxUser = user2WxUser(strObj, user);
        wxUserMapper.save(wxUser);

        //6.免密登录
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token, logininfo, 30, TimeUnit.MINUTES);
        Map<String,Object> map = new HashMap<>();
        map.put("token", token);
        //作为一个高级技师 我们不能将账号和密码传给前端,应该过滤掉
        logininfo.setUsername(null);
        logininfo.setPassword(null);
        map.put("logininfo",logininfo);
        return AjaxResult.me().setResultObj(map);//免密登录成功返回
    }


    private WxUser user2WxUser(String wxUserStr, User user) {
        //装换微信用户信息
        JSONObject jsonObject = JSONObject.parseObject(wxUserStr);
        WxUser wxUser =  new WxUser();
        wxUser.setUser_id(user.getId());    // 绑定平台用户
        wxUser.setOpenid(jsonObject.getString("openid"));
        wxUser.setNickname(jsonObject.getString("nickname"));
        wxUser.setSex(jsonObject.getInteger("sex"));
        wxUser.setAddress(null);
        wxUser.setHeadimgurl(jsonObject.getString("headimgurl"));
        wxUser.setUnionid(jsonObject.getString("unionid"));
        return wxUser;
    }


    private User loginInfo2User(Logininfo info) {
        User user = new User();
        BeanUtils.copyProperties(info,user);//根据同名原则拷贝
        return user;
    }

    /**
     * 通过Phone创建info
     */
    private Logininfo createLoginInfo(String phone) {
        Logininfo info = new Logininfo();
        info.setUsername(phone);
        info.setPhone(phone);
        //设置一个默认密码  todo:默认密码可以发短信告知用户
        String salt = StrUtils.getComplexRandomString(32);
        String md5Pwd = MD5Utils.encrypByMd5(StrUtils.getComplexRandomString(6) + salt);
        info.setType(1);//设置前端type值
        info.setSalt(salt);
        info.setPassword(md5Pwd);
        return info;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/41408.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Dart】006-类的定义和使用

【Dart】006-类的定义和使用 文章目录 【Dart】006-类的定义和使用一、类的定义1、概述2、简单定义与实例化代码示例运行结果 3、成员方法代码示例运行结果箭头函数写法 4、get 与 set 关键字概述代码示例运行结果 二、类的构造方法1、特点2、完整版的构造方法简化版完整版 3、…

【JavaScript】Function的祖传方法call与apply

引言 内容速递 看了本文您能了解到的知识&#xff01; 在本篇文章中&#xff0c;将带你了解什么是call和apply&#xff0c;call和apply的用途、如何手写call和apply以及call和apply的使用场景。 1、什么是call和apply call()和apply()是JavaScript中的两个内置方法&#xff…

天翎MyApps低代码平台唯品会金牌客服管理系统

项目痛点&#xff1a; 作为一家知名的创新大型电商&#xff0c;唯品会秉承“传承品质生活&#xff0c;提升幸福体验”的企业使命。基于客服铁军锻造项目&#xff0c;实现基于金牌案例的提交、评审、积分&#xff0c;学习功能。 项目中的晋升机制、案例产生学习机制、双激励机制…

STM32之按键驱动的使用和自定义(MultiButton)

原始Github地址 Github地址 修改后 调整内容 将宏定义转换成配置结构体 头文件 #ifndef _MULTI_BUTTON_H_ #define _MULTI_BUTTON_H_#include "stdint.h" #include "string.h"//According to your need to modify the constants. //#define TICKS_IN…

HarmonyOS/OpenHarmony应用开发-Stage模型UIAbility组件使用(四)

UIAbility组件与UI的数据同步 基于HarmonyOS的应用模型&#xff0c;可以通过以下两种方式来实现UIAbility组件与UI之间的数据同步。 1.EventHub&#xff1a;基于发布订阅模式来实现&#xff0c;事件需要先订阅后发布&#xff0c;订阅者收到消息后进行处理。 2.globalThis&…

MySQL日常操作记录

1.查看MySQL版本 select version();2.快速复制表结构&#xff0c;不包含相关主键及约束 create table user_test as select * from user where 12;3.uuid select uuid(),uuid_short();4.替换uuid()里的’-‘为’’ select replace(uuid(),-,);5.md5摘要 select md5(uuid()…

HBase(一)HBase v2.2 高可用多节点搭建

最近刚刚完成了HBase相关的一个项目,作为项目的技术负责人,完成了大部分的项目部署,特性调研工作,以此系列文章作为上一阶段工作的总结. 前言 其实目前就大多数做应用的情况来讲,我们并不需要去自己搭建一套HBase的集群,现有的很多云厂商提供的服务已经极大的方便日常的应用使…

rce题目

<?php include "flag.php"; highlight_file(__FILE__); if(isset($_GET[HECTF])) { if (; preg_replace(/[^\W]\((?R)?\)/, NULL, $_GET[HECTF])) { if (!preg_match(/pos|high|op|na|info|dec|hex|oct|pi/i, $_GET[HECTF])) { eval(…

NSSCTF刷web(2)

[NISACTF 2022]bingdundun~ bingdundun处感觉像文件包含,改upload为index 发现确实,猜测会补一个后缀.php 那常规文件包含都不行了,这里还有一个文件上传的功能,考虑phar协议 <?php$phar new Phar("test.phar"); $phar->startBuffering(); $phar->setStu…

C++入门学习(2)

思维导图&#xff1a; 一&#xff0c;缺省参数 如何理解缺省参数呢&#xff1f;简单来说&#xff0c;缺省参数就是一个会找备胎的参数&#xff01;为什么这样子说呢&#xff1f;来看一个缺省参数就知道了&#xff01;代码如下&#xff1a; #include<iostream> using std…

算法与数据结构-排序

文章目录 一、如何分析一个排序算法1.1 排序算法的执行效率1.1.1 最好情况、最坏情况、平均情况时间复杂度1.1.1.1 最好、最坏情况分析1.1.1.2 平均情况分析 1.1.2 时间复杂度的系数、常数 、低阶1.1.3 比较次数和交换&#xff08;或移动&#xff09;次数 1.2 排序算法的内存消…

Go语言之重要数组类型map(映射)类型

通过切片&#xff0c;我们可以动态灵活存储管理学生姓名、年龄等信息&#xff0c;比如 names : []string{"张三","李四","王五"} ages : []int{23,24,25} fmt.Println(names) fmt.Println(ages)但是如果我想获取张三的年龄&#xff0c;这是一个…

C# 同构字符串

205 同构字符串 给定两个字符串 s 和 t &#xff0c;判断它们是否是同构的。 如果 s 中的字符可以按某种映射关系替换得到 t &#xff0c;那么这两个字符串是同构的。 每个出现的字符都应当映射到另一个字符&#xff0c;同时不改变字符的顺序。不同字符不能映射到同一个字符…

详细介绍MATLAB中的图论算法

MATLAB是一种功能强大的编程语言和环境,提供了许多用于图论算法的工具和函数。图论是研究图及其属性和关系的数学分支,广泛应用于计算机科学、网络分析、社交网络分析等领域。在MATLAB中,我们可以使用图论算法来解决各种问题,如最短路径问题、最小生成树问题、最大流问题等…

国产MCU-CW32F030开发学习-BH1750模块

国产MCU-CW32F030开发学习-BH1750模块 硬件平台 CW32_48F大学计划板CW32_IOT_EVA物联网开发评估套件BH1750数字型光照强度传感器 BH1750 BH1750是一款数字型光照强度传感器&#xff0c;能够获取周围环境的光照强度。其测量范围在0~65535 lx。lx勒克斯&#xff0c;是光照强…

【电路效应】信号处理和通信系统模型中的模拟电路效应研究(SimulinkMatlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f308;4 Matlab代码、Simulink仿真实现 &#x1f4a5;1 概述 在信号处理和通信系统模型中&#xff0c;模拟电路效应研究是指考虑到实际电路的特性对信号进行建模和分析的过程。模拟电路效应…

Kubernetes—集群故障排查

一、用 Kubectl 调试 Kubernetes 节点 准备开始 你必须拥有一个 Kubernetes 的集群&#xff0c;同时你必须配置 kubectl 命令行工具与你的集群通信。 建议在至少有两个不作为控制平面主机的节点的集群上运行本教程。 你的 Kubernetes 服务器版本必须不低于版本 1.2. 要获知版…

C#基础--委托

C#基础–委托 C#基础–委托 简单说它就是一个能把方法当参数传递的对象&#xff0c;而且还知道怎么调用这个方法&#xff0c;同时也是粒度更小的“接口”&#xff08;约束了指向方法的签名&#xff09; 一、什么是委托&#xff0c;委托的本质是什么&#xff1f; 跟方法有点类似…

云迁移第二波热潮来袭,你准备好了吗?

最近&#xff0c;云迁移再次被频繁提及&#xff0c;企业对云迁移的需求量有回升趋势&#xff0c;究其根本&#xff0c;主要有以下原因&#xff1a; 企业数字化进程加速&#xff0c;本地上云需求强劲 根据《2021中国企业上云指数洞察报告》&#xff0c;我国实体经济上云渗透率…

深入理解Java虚拟机(二)Java内存区域与内存溢出异常

一、前言 对于Java程序员来说&#xff0c;在虚拟机自动内存管理机制的帮助下&#xff0c;不再需要为每一个new操作去写配对的delete/free代码&#xff0c;不容易出现内存泄漏和内存溢出问题&#xff0c;看起来由虚拟机管理内存一切都很美好。不过&#xff0c;也正是因为Java程序…