【谷粒商城之服务认证OAuth2.0】

news2024/9/22 17:35:09

本笔记内容为尚硅谷谷粒商城服务认证OAuth2.0部分

目录

一、OAuth 2.0

二、微博登录测试

1、微博登陆准备工作 

2、获取微博Access Token

3、登录测试

1.添加HttpUtils工具类

2.controller

3.service

4.vo

总结


一、OAuth 2.0


  • OAuth: OAuth(开放授权)是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容。
  • OAuth2.0:对于用户相关的 OpenAPI(例如获取用户信息,动态同步,照片,日志,分享等),为了保护用户数据的安全和隐私,第三方网站访问用户数据前都需要显式的向用户征求授权。

官方版流程:

(A)用户打开客户端以后,客户端要求用户给予授权。
(B)用户同意给予客户端授权。
(C)客户端使用上一步获得的授权,向认证服务器申请令牌。
(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
(E)客户端使用令牌,向资源服务器申请获取资源。
(F)资源服务器确认令牌无误,同意向客户端开放资源。

二、微博登录测试


  1. Client(第三方应用,gulimall)给User Agent(用户代理,浏览器)发请求,相当于在第三方网站点了微博登录的按钮
  2. 浏览器携带客户端的标识和重定向的地址,还有用户的认证信息(账号密码),去向微博认证服务器进行认证,认证成功会跳转回浏览器,并给出一个授权码。
  3. 浏览器会将授权码给到第三方网站,第三方网站拿着授权码和重定向地址,向微博认证服务器交换一个访问令牌,第三方网站就拿着访问令牌来调用微博的api。

1、微博登陆准备工作 

不使用微博也可以使用gitee等等来测试 

1、进入微博开放平台

2、登陆微博,进入微连接,选择网站接入

3、选择立即接入

4、创建自己的应用

5、我们可以在开发阶段进行测试了

6、进入高级信息,填写授权回调页的地址

7、进入文档,按照流程测试社交登陆

2、获取微博Access Token

1.引导需要授权的用户到如下地址:

// client_id 上面的 App Key
// redirect_uri 上面配置的授权回调页
https://api.weibo.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=YOUR_REGISTERED_REDIRECT_URI

2.如果用户同意授权,页面跳转至 YOUR_REGISTERED_REDIRECT_URI/?code=CODE,得到code码

3.使用返回的CODE换取Access Token

  • 一个CODE只能换取一次Access Token
  • 同一个用户的Access Token在一段时间是不会变化的,即使用多个不同的code获取
https://api.weibo.com/oauth2/access_token?client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=authorization_code&redirect_uri=YOUR_REGISTERED_REDIRECT_URI&code=CODE

注意,上面这个是 post 请求

4.使用 AccessToken 调用开发 API 获取用户信息

Oauth2.0;授权通过后,使用 code 换取 access_token,然后去访问任何开放 API
1)、code 用后即毁
2)、access_token 在几天内是一样的
3)、uid 永久固定

3、登录测试

1.添加HttpUtils工具类

HttpUtils放进 common服务中方便调用

package com.atguigu.common.utils;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

public class HttpUtils {

    /**
     * get
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @return
     * @throws Exception
     */
    public static HttpResponse doGet(String host, String path, String method,
                                     Map<String, String> headers,
                                     Map<String, String> querys)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpGet request = new HttpGet(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        return httpClient.execute(request);
    }

    /**
     * post form
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param bodys
     * @return
     * @throws Exception
     */
    public static HttpResponse doPost(String host, String path, String method,
                                      Map<String, String> headers,
                                      Map<String, String> querys,
                                      Map<String, String> bodys)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (bodys != null) {
            List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>();

            for (String key : bodys.keySet()) {
                nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key)));
            }
            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8");
            formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
            request.setEntity(formEntity);
        }

        return httpClient.execute(request);
    }

    /**
     * Post String
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPost(String host, String path, String method,
                                      Map<String, String> headers,
                                      Map<String, String> querys,
                                      String body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (StringUtils.isNotBlank(body)) {
            request.setEntity(new StringEntity(body, "utf-8"));
        }

        return httpClient.execute(request);
    }

    /**
     * Post stream
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPost(String host, String path, String method,
                                      Map<String, String> headers,
                                      Map<String, String> querys,
                                      byte[] body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (body != null) {
            request.setEntity(new ByteArrayEntity(body));
        }

        return httpClient.execute(request);
    }

    /**
     * Put String
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPut(String host, String path, String method,
                                     Map<String, String> headers,
                                     Map<String, String> querys,
                                     String body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpPut request = new HttpPut(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (StringUtils.isNotBlank(body)) {
            request.setEntity(new StringEntity(body, "utf-8"));
        }

        return httpClient.execute(request);
    }

    /**
     * Put stream
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPut(String host, String path, String method,
                                     Map<String, String> headers,
                                     Map<String, String> querys,
                                     byte[] body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpPut request = new HttpPut(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (body != null) {
            request.setEntity(new ByteArrayEntity(body));
        }

        return httpClient.execute(request);
    }

    /**
     * Delete
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @return
     * @throws Exception
     */
    public static HttpResponse doDelete(String host, String path, String method,
                                        Map<String, String> headers,
                                        Map<String, String> querys)
            throws Exception {
        HttpClient httpClient = wrapClient(host);

        HttpDelete request = new HttpDelete(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        return httpClient.execute(request);
    }

    private static String buildUrl(String host, String path, Map<String, String> querys) throws UnsupportedEncodingException {
        StringBuilder sbUrl = new StringBuilder();
        sbUrl.append(host);
        if (!StringUtils.isBlank(path)) {
            sbUrl.append(path);
        }
        if (null != querys) {
            StringBuilder sbQuery = new StringBuilder();
            for (Map.Entry<String, String> query : querys.entrySet()) {
                if (0 < sbQuery.length()) {
                    sbQuery.append("&");
                }
                if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) {
                    sbQuery.append(query.getValue());
                }
                if (!StringUtils.isBlank(query.getKey())) {
                    sbQuery.append(query.getKey());
                    if (!StringUtils.isBlank(query.getValue())) {
                        sbQuery.append("=");
                        sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8"));
                    }
                }
            }
            if (0 < sbQuery.length()) {
                sbUrl.append("?").append(sbQuery);
            }
        }

        return sbUrl.toString();
    }

    private static HttpClient wrapClient(String host) {
        HttpClient httpClient = new DefaultHttpClient();
        if (host.startsWith("https://")) {
            sslClient(httpClient);
        }

        return httpClient;
    }

    private static void sslClient(HttpClient httpClient) {
        try {
            SSLContext ctx = SSLContext.getInstance("TLS");
            X509TrustManager tm = new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                public void checkClientTrusted(X509Certificate[] xcs, String str) {

                }
                public void checkServerTrusted(X509Certificate[] xcs, String str) {

                }
            };
            ctx.init(null, new TrustManager[] { tm }, null);
            SSLSocketFactory ssf = new SSLSocketFactory(ctx);
            ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            ClientConnectionManager ccm = httpClient.getConnectionManager();
            SchemeRegistry registry = ccm.getSchemeRegistry();
            registry.register(new Scheme("https", 443, ssf));
        } catch (KeyManagementException ex) {
            throw new RuntimeException(ex);
        } catch (NoSuchAlgorithmException ex) {
            throw new RuntimeException(ex);
        }
    }
}

导入依赖

<!--导入 org.apache.http.client.HttpClient等依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.15</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.2.1</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-util</artifactId>
            <version>9.3.7.v20160115</version>
        </dependency>
        <!--<dependency>-->
        <!--    <groupId>junit</groupId>-->
        <!--    <artifactId>junit</artifactId>-->
        <!--    <version>4.5</version>-->
        <!--    <scope>test</scope>-->
        <!--</dependency>-->

2.controller

authserver

/**
 * 处理社交登录请求
 */
@Controller
@Slf4j
public class OAuth2Controller {


    @Autowired
    MemberFeignService memberFeignService;
    @GetMapping("/auth2.0/weibo/success")
    public String weibo(@RequestParam("code") String code) throws Exception {

        // 1. 根据登录微博返回的code换取accessToken
        Map<String,String> map = new HashMap<>();

        map.put("client_id","1657382705");
        map.put("client_secret","ca422dd82a99de49026332a9ecf6a7c4");
        map.put("grant_type","authorization_code");
        map.put("redirect_uri","http://auth.gulimall.com/auth2.0/weibo/success");
        map.put("code",code);



        HttpResponse response = HttpUtils.doPost("https://api.weibo.com", "/oauth2/access_token", "post",
                null, null, map);

        if (response.getStatusLine().getStatusCode()==200){
            // 获取到了accessToken
            String json = EntityUtils.toString(response.getEntity());
            SocialUser socialUser = JSON.parseObject(json, SocialUser.class);

            // 知道了当前是哪个微博用户
            // 1. 当前用户如果是第一次进网站,自动注册进来(为当前社交用户生成一个会员信息账号,
            // 以后这个社交账号就对应我们指定的会员)
            R oauthLogin = memberFeignService.oauthLogin(socialUser);
            if (oauthLogin.getCode()==0){
                // 2. 登录成功就跳回首页
                MemberRespVo data = oauthLogin.getData(new TypeReference<MemberRespVo>() {});
                System.out.println("登录成功:用户信息" + data);
                log.info("登录成功:用户信息:{}",data.toString());
                return "redirect:http://gulimall.com";
            }else {
                return "redirect:http://auth.gulimall.com/login.html";
            }

            // 登录或者注册这个社交用户
        }else {
            return "redirect:http://auth.gulimall.com/login.html";
        }



    }
}

member

@RefreshScope
@RestController
@RequestMapping("member/member")
public class MemberController {
    @Autowired
    private MemberService memberService;

    @Autowired
    CouponFeignService couponFeignService;

    @Value("${member.name}")
    private String memberName;

    @Value("${member.age}")
    private String memberAge;


    @PostMapping("/oauth2/login")
    public R oauthLogin(@RequestBody SocialUser socialUser) throws Exception {

        MemberEntity memberEntity = memberService.login(socialUser);

        if (memberEntity!=null){
            return R.ok().setData(memberEntity);
        }else {
            return R.error(BizCodeEnume.LOGINACCT_PASSWORD_INVALID_EXCEPTION.getCode(),
                    BizCodeEnume.LOGINACCT_PASSWORD_INVALID_EXCEPTION.getMessage());
        }


    }

3.service

MemberServiceImpl

@Override
    public MemberEntity login(SocialUser socialUser) throws Exception {
        // 登录和注册合并逻辑
        String uid = socialUser.getUid();
        // 1. 判断当前社交用户是否已经登陆过系统
        MemberEntity memberEntity = baseMapper.selectOne(new QueryWrapper<MemberEntity>().eq("social_uid", uid));

        if (memberEntity!=null){
            // 这个用户已经注册了
            MemberEntity update = new MemberEntity();
            update.setId(memberEntity.getId());
            update.setAccessToken(socialUser.getAccess_token());
            update.setExpiresIn(socialUser.getExpires_in());
            baseMapper.updateById(update);

            memberEntity.setExpiresIn(socialUser.getExpires_in());
            memberEntity.setAccessToken(socialUser.getAccess_token());

            return memberEntity;
        }else {
            // 2. 没有查到当前社交用户对应的记录,我们就需要注册一个
            MemberEntity regist = new MemberEntity();
            try {
// 3. 查询当前社交用户的社交账号信息(昵称,性别等)
                Map<String,String> query = new HashMap<>();
                query.put("access_token", socialUser.getAccess_token());
                query.put("uid", socialUser.getUid());
                HttpResponse response = HttpUtils.doGet("https://api.weibo.com", "/2/users/show.json", "get",
                        new HashMap<String, String>(), query);

                if (response.getStatusLine().getStatusCode() == 200){
                    // 查询成功
                    String json = EntityUtils.toString(response.getEntity());
                    JSONObject jsonObject = JSON.parseObject(json);
                    // 昵称
                    String name = jsonObject.getString("name");
                    String gender = jsonObject.getString("gender");
                    // 获取微博返回的其他信息。。。。。。
                    regist.setGender("m".equals(gender)?1:0);



                }
            }catch (Exception e){


            }


            regist.setSocialUid(socialUser.getUid());
            regist.setAccessToken(socialUser.getAccess_token());
            regist.setExpiresIn(socialUser.getExpires_in());
            baseMapper.insert(regist);

            return regist;
        }

    }

远程调用:认证服务调用会员服务

认证服务feign包下的MemberFeignService

@FeignClient("gulimall-member")
    @PostMapping("/member/member/oauth2/login")
    R oauthlogin(@RequestBody SocialUser socialUser) throws Exception;

4.vo

SocialUser 

package com.atguigu.gulimall.authserver.vo;

import lombok.Data;

@Data
public class SocialUser {

    private String access_token;
    private String remind_in;
    private long expires_in;
    private String uid;
    private String isRealName;
}

MemberRespVo

为member表新增三个字段

 

package com.atguigu.gulimall.authserver.vo;

import lombok.Data;
import lombok.ToString;

import java.util.Date;

@Data
@ToString
public class MemberRespVo {

    /**
     * id
     */
    private Long id;
    /**
     * 会员等级id
     */
    private Long levelId;
    /**
     * 用户名
     */
    private String username;
    /**
     * 密码
     */
    private String password;
    /**
     * 昵称
     */
    private String nickname;
    /**
     * 手机号码
     */
    private String mobile;
    /**
     * 邮箱
     */
    private String email;
    /**
     * 头像
     */
    private String header;
    /**
     * 性别
     */
    private Integer gender;
    /**
     * 生日
     */
    private Date birth;
    /**
     * 所在城市
     */
    private String city;
    /**
     * 职业
     */
    private String job;
    /**
     * 个性签名
     */
    private String sign;
    /**
     * 用户来源
     */
    private Integer sourceType;
    /**
     * 积分
     */
    private Integer integration;
    /**
     * 成长值
     */
    private Integer growth;
    /**
     * 启用状态
     */
    private Integer status;
    /**
     * 注册时间
     */
    private Date createTime;

    private String socialUid;
    private String accessToken;
    private Long expiresIn;
}

测试

登录成功返回首页(这里很容易出现 超时现象,多试几次即可。)

总结

结束! 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【账号激活】

由于注册时会遇到诸多错误提示&#xff01;所以出此详细教程。 重点是要巧妙的运用无痕浏览窗口。 步骤分为两步&#xff0c;sign up 激活邮箱以及 log in 短信验证码验证。 右上角新建无痕浏览窗口。新建完后记得关闭此有痕浏览窗口。 成功创建。完成第一步。 若要连续操作切记…

双极性信号、正交信号和PAM信号通信系统matlab程序+仿真

资源地址&#xff1a; 双极性信号、正交信号和PAM信号通信系统MATLAB程序仿真资源-CSDN文库 部分程序及仿真图&#xff1a; clear all EbN00:10; %SNR的范围 for ii1:length(EbN0) SNREbN0(ii); %赋值给AWGN信道模块中的SNR sim(ex5); %运行仿…

【Java笔试强训 24】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一、选择题 二、编程题 &#x1f525;年终奖 …

一般对称性和轮换对称性

一般对称性 一元函数的对称性 几何意义是所围图形的面积绝对值 【注】使用对称性的时候&#xff0c;首先抓积分区域关于哪个轴对称&#xff0c;其次抓被积函数是为另一轴的奇&#xff08;偶函数&#xff09;。 二元函数的对称性(奇偶性) 【注】在一般对称性中&#xff0c;(x…

MCU固件升级系列1(STM32)

本系列将从升级流程、boot代码编写、APP代码编写以及固件打包来介绍&#xff0c;硬件选用STM32F407ZGT6&#xff08;手里只有&#xff09;&#xff0c;来完成这系列教程。 前言 为什么需要固件升级: 功能更新&#xff1a;随着产品的迭代和用户需求的变化&#xff0c;可能需要…

【DM】达梦数据库与MySQL适配

一、达梦入门技术文档 新手直接看达梦入门技术文档即可 二、达梦数据库 1、介绍 达梦数据库管理系统是达梦公司推出的具有完全自主知识产权的高性能数据库管理系统&#xff0c;简称DM&#xff0c;它具有如下特点&#xff1a;通用性、高性能、高可用、跨平台、高可扩展 2、与…

网络安全:windows批处理写病毒的一些基本命令.

网络安全&#xff1a;windows批处理一些命令. echo off一般都写在批处理的最上面&#xff0c;用于关闭回显&#xff0c;意思是 关闭回显&#xff1a; 没有关闭回显: 所以&#xff0c;意思就是将输入指令的过程隐藏起来。 set是设置的意思&#xff0c;作业是打印、创建和修改变…

【算法】求最短路径算法

文章目录 一、迪杰斯特拉算法1.1 算法介绍1.2 算法步骤1.3 应用场景 二、弗洛伊德算法2.1 算法介绍2.2 算法步骤2.3 应用场景 一、迪杰斯特拉算法 1.1 算法介绍 从某顶点出发&#xff0c;沿图的边到达另一顶点所经过的路径中&#xff0c;各边上权值之和最小的一条路径叫做最短…

Hausdorff distance

Hausdorff距离量度度量空间中紧子集之间的距离 定义 设 X X X和 Y Y Y是度量空间 M M M的两个紧子集 d H ( X , Y ) max ⁡ { sup ⁡ x ∈ X inf ⁡ y ∈ Y d ( x , y ) , sup ⁡ y ∈ Y inf ⁡ x ∈ X d ( x , y ) } d_H\left(X, Y\right) \max \left\{\sup_{x\in X} \in…

Linux — 多线程的互斥与同步,信号量

1.线程互斥 进程线程间的互斥相关背景概念 临界资源&#xff1a;多线程执行流共享的资源就叫做临界资源。临界区&#xff1a;每个线程内部&#xff0c;访问临界资源的代码&#xff0c;就叫做临界区。互斥&#xff1a;任何时刻&#xff0c;互斥保证有且只有一个执行流进入临界区…

利用粒子群算法设计无线传感器网络中的最优安全路由模型(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 无线传感器网络&#xff08;WSN&#xff09;由数十个、数百个甚至数千个自主传感器组成。这些传感器以无线方式嵌入环境中&…

Day49 5.01 C++刷题

Go不是解释型语言&#xff0c;是编译型语言 Java是混合型语言

MOSFET正向导通,阻断,阈值电压研究

一 设计要求&#xff1a; N-为均匀掺杂、其他均为离子注入所形成的高斯掺杂&#xff1b;P的宽度为10、结深6um&#xff1b;氧化层oxide厚度为0.1um,宽度为10um&#xff1b;氧化层左侧空白需要定义为材料air&#xff1b;所有电极都定义为无厚度&#xff1b;所有的高斯掺杂峰值点…

( 数组和矩阵) 485. 最大连续 1 的个数 ——【Leetcode每日一题】

❓485. 最大连续 1 的个数 难度&#xff1a;简单 给定一个二进制数组 nums &#xff0c; 计算其中最大连续 1 的个数。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,0,1,1,1] 输出&#xff1a;3 解释&#xff1a;开头的两位和最后的三位都是连续 1 &#xff0c;所以最大…

Vision Transformer架构Pytorch逐行实现

前言 代码来自哔哩哔哩博主deep_thoughts&#xff0c;视频地址&#xff0c;该博主对深度学习框架方面讲的非常详细&#xff0c;推荐大家也去看看原视频&#xff0c;不管是否已经非常熟练&#xff0c;我相信都能有很大收获。论文An Image is Worth 16x16 Words: Transformers f…

iOS审核这些坑,腾讯游戏也踩过

WeTest 导读 在App上架苹果应用商店的过程中&#xff0c;相信大多数iOS开发者往往都有过这样的经历&#xff1a;辛苦开发出来的产品&#xff0c;测试验收也通过了&#xff0c;满怀期待的提交App给苹果审核&#xff0c;结果经常被苹果各种理由拒之门外&#xff0c;苦不堪言。 …

Prometheus监控系统存储容量优化攻略,让你的数据安心保存!

云原生监控领域不可撼动&#xff0c;Prometheus 是不是就没缺点&#xff1f;显然不是。 一个软件如果什么问题都想解决&#xff0c;就会导致什么问题都解决不好。所以Prometheus 也存在不足&#xff0c;广受诟病的问题就是 单机存储不好扩展。 1 真的需要扩展容量吗&#xff…

0x80070570文件或目录损坏且无法读取解决方法

第一种解决方法&#xff1a;命令提示符修复。 1、首先按下“Win标R”键&#xff0c;打开运行。 2、然后如果要修复的文件在E盘&#xff0c;那就输入&#xff1a;chkdsk e: /f&#xff0c;h盘就是&#xff1a;chkdsk h: /f&#xff0c;反正是哪个盘就把中间的字幕改成那个盘的…

ecs思考

VPC网络诊断&#xff0c;从router看起&#xff0c;连接公有子网路有一个默认&#xff0c;再新增一条指向igw路由&#xff1b;连接私有子网路由有一个默认&#xff0c;再新增一条指向NAT网关的路由&#xff0c;其中NAT网关一定要在公有子网中&#xff0c;否则&#xff0c;私有子…

Android 10.0 设置默认浏览器后安装另外浏览器后默认浏览器功能修复

1.前言 在10.0的系统rom定制化开发中,当在系统中有多个浏览器的时候,会在用代码启用浏览器的时候,让用户选择进入哪个浏览器,这样显得特别的不方便 所以产品开发中,要求用RoleManager的相关api来设置默认浏览器,但是在设置完默认浏览器以后,在安装一款浏览器的时候,默认…