微服务实战——登录(普通登录、社交登录、SSO单点登录)

news2024/11/28 7:42:11

登录

1.1. 用户密码

@PostMapping("/login")
    public String login(UserLoginVo vo, RedirectAttributes redirectAttributes, HttpSession session){
        R r = memberFeignService.login(vo);
        if(r.getCode() == 0){
            MemberRespVo data = r.getData("data", new TypeReference<MemberRespVo>() {
            });
            session.setAttribute("loginUser", data);
            return "redirect:http://gulimall.com";
        }else {
            Map<String, String> errors = new HashMap<>();
            errors.put("msg", r.getData("msg", new TypeReference<String>(){}));
            redirectAttributes.addFlashAttribute("errors", errors);
            return "redirect:http://auth.gulimall.com/login.html";
        }
    }

    @GetMapping("/login.html")
    public String loginPage(HttpSession session){
        Object loginUser = session.getAttribute("loginUser");
        if(loginUser != null){
            return "redirect:http://gulimall.com";
        }
        return "login";
    }
@Override
    public MemberEntity login(MemberLoginVo vo) {

        String loginacct = vo.getLoginacct();
        String password = vo.getPassword();
        MemberEntity memberEntity = this.getOne(new QueryWrapper<MemberEntity>()
                .eq("username", loginacct)
                .or().eq("mobile", loginacct));
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        if(memberEntity == null){
            return null;
        }
        if (passwordEncoder.matches(password, memberEntity.getPassword())) {
            return memberEntity;
        }
        return null;
    }

1.2. 社交登录

QQ 、微博、 github 等网站的用户量非常大,别的网站为了简化自我网站的登陆与注册逻辑,引入社交登陆功能;

步骤:

1 )、用户点击 QQ 按钮

2 )、引导跳转到 QQ 授权页

3)、用户主动点击授权,跳回之前网页。

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

  • 官方版流程:

(A )用户打开客户端以后,客户端要求用户给予授权。

(B )用户同意给予客户端授权。

(C )客户端使用上一步获得的授权,向认证服务器申请令牌。

(D )认证服务器对客户端进行认证以后,确认无误,同意发放令牌。

(E )客户端使用令牌,向资源服务器申请获取资源。

(F )资源服务器确认令牌无误,同意向客户端开放资源。

OAuth2.0流程:

  • 使用Code换取AccessToken,Code只能用一次
  • 同一个用户的accessToken一段时间是不会变化的,即使多次获取
1.2.2. 代码实现

1)、进入微博开放平台

微博组件_微博开放平台

2)、添加社交登录回调接口

认证接口

  • 通过HttpUtils发送请求获取token,并将token等信息交给member服务进行社交登录
  • 若获取token失败或远程调用服务失败,则封装错误信息重新转回登录页

修改“com.cwh.gulimall.auth.feign.MemberFeignService”类,代码如下:

@PostMapping("/member/member/oauth2/login")
public R oauth2Login(@RequestBody SocialUser socialUser);

添加“com.cwh.gulimall.auth.vo.SocialUser”类,代码如下:

package com.cwh.gulimall.auth.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;
}

添加“com.cwh.gulimall.auth.vo.MemberResponseVO”类,代码如下:

package com.cwh.gulimall.auth.vo;
 
import lombok.Data;
import lombok.ToString;
 
import java.util.Date;
 
@ToString
@Data
public class MemberResponseVO {
    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;
}

添加“com.cwh.gulimall.auth.controller.Oauth2Controller”类,代码如下:

@Controller
public class OauthController {

    @Autowired
    private MemberFeignService memberFeignService;

    @RequestMapping("/oauth2.0/weibo/success")
    public String authorize(String code, RedirectAttributes attributes) throws Exception {
        // 1、使用code换取token,换取成功则继续2,否则重定向至登录页
        Map<String, String> query = new HashMap<>();
        query.put("client_id", "2144***074");
        query.put("client_secret", "ff63a0d8d5*****29a19492817316ab");
        query.put("grant_type", "authorization_code");
        query.put("redirect_uri", "http://auth.gulimall.com/oauth2.0/weibo/success");
        query.put("code", code);
        // 发送post请求换取token
        HttpResponse response = HttpUtils.doPost("https://api.weibo.com", "/oauth2/access_token", "post", new HashMap<String, String>(), query, new HashMap<String, String>());
        Map<String, String> errors = new HashMap<>();
        if (response.getStatusLine().getStatusCode() == 200) {
            // 2. 调用member远程接口进行oauth登录,登录成功则转发至首页并携带返回用户信息,否则转发至登录页
            String json = EntityUtils.toString(response.getEntity());
            SocialUser socialUser = JSON.parseObject(json, new TypeReference<SocialUser>() {
            });
            R login = memberFeignService.login(socialUser);
            // 2.1 远程调用成功,返回首页并携带用户信息
            if (login.getCode() == 0) {
                String jsonString = JSON.toJSONString(login.get("memberEntity"));
                MemberResponseVo memberResponseVo = JSON.parseObject(jsonString, new TypeReference<MemberResponseVo>() {
                });
                attributes.addFlashAttribute("user", memberResponseVo);
                return "redirect:http://gulimall.com";
            }else {
                // 2.2 否则返回登录页
                errors.put("msg", "登录失败,请重试");
                attributes.addFlashAttribute("errors", errors);
                return "redirect:http://auth.gulimall.com/login.html";
            }
        }else {
            errors.put("msg", "获得第三方授权失败,请重试");
            attributes.addFlashAttribute("errors", errors);
            return "redirect:http://auth.gulimall.com/login.html";
        }
    }

登录接口

  • 登录包含两种流程,实际上包括了注册和登录
  • 如果之前未使用该社交账号登录,则使用token调用开放api获取社交账号相关信息,注册并将结果返回
  • 如果之前已经使用该社交账号登录,则更新token并将结果返回

添加“com.cwh.gulimall.member.vo.SocialUser”类,代码如下:

package com.cwh.gulimall.member.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;
}
修改“com.cwh.gulimall.member.controller.MemberController”类,代码如下:

    @PostMapping("/oauth2/login")
    public R oauth2Login(@RequestBody SocialUser socialUser){
        MemberEntity entity = memberService.login(socialUser);
        if (entity != null){
            return R.ok().setData(entity);
        }else {
            return R.error(BizCodeEnume.LOGINACCT_PASSWORD_INVAILD_EXCEPTION.getCode(),BizCodeEnume.LOGINACCT_PASSWORD_INVAILD_EXCEPTION.getMsg());
        }
 
    }

修改gulimall_ums.ums_member表结构,sql如下:

ALTER TABLE `gulimall_ums`.`ums_member` 
ADD COLUMN `social_uid` varchar(255) NULL COMMENT '社交用户id' AFTER `create_time`,
ADD COLUMN `access_token` varchar(255) NULL COMMENT '访问token' AFTER `social_uid`,
ADD COLUMN `expires_in` int NULL COMMENT '过期时间戳' AFTER `access_token`;

修改“com.cwh.gulimall.member.entity.MemberEntity”类,新增三个属性,代码如下:

修改“com.cwh.gulimall.member.service.MemberService”类,代码如下:

MemberEntity login(SocialUser socialUser);

修改“com.cwh.gulimall.member.service.impl.MemberServiceImpl”类,代码如下:

@Override
public MemberEntity login(SocialUser socialUser) {
// 1 根据 uid 判断当前用户是否以前用社交平台登录过系统
MemberEntity memberEntity = this.baseMapper.selectOne(new QueryWrapper<MemberEntity>().eq("social_uid", socialUser.getUid()));
if (!StringUtils.isEmpty(memberEntity)) {
    // 说明这个用户之前已经注册过
    MemberEntity update = new MemberEntity();
    update.setId(memberEntity.getId());
    update.setAccessToken(socialUser.getAccess_token());
    update.setExpiresIn(socialUser.getExpires_in());
    this.baseMapper.updateById(update);

    memberEntity.setAccessToken(socialUser.getAccess_token());
    memberEntity.setExpiresIn(socialUser.getExpires_in());
    return memberEntity;
} else {
    // 未找到则注册 根据社交平台的开放接口查询用户的开放信息存储到系统
    MemberEntity register = new MemberEntity();
    try {
        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<>(), 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");
            // ......
            register.setNickname(name);
            register.setGender("m".equals(gender) ? 1 : 0);
            // .....
        }
    } catch (Exception e) {
        log.warn("调用微博接口获取信息异常{}", e);
    }
    register.setSocialUid(socialUser.getUid());
    register.setAccessToken(socialUser.getAccess_token());
    register.setExpiresIn(socialUser.getExpires_in());
    this.baseMapper.insert(register);
    return register;
}

小结

Oauth2.0 ;授权通过后,使用 code 换取 access_token ,然后去访问任何开放 API

1 )、 code 用后即毁

2 )、 access_token 在几天内是一样的

3 )、 uid 永久固定

1.3. SpringSession

1.3.1. Session共享问题
1.3.1.1. session原理

jsessionid相当于银行卡,存在服务器的session相当于存储的现金,每次通过jsessionid取出保存的数据。

问题:但是正常情况下session不可跨域,它有自己的作用范围

1.3.1.2. 分布式下session共享问题

  • 同一个服务,复制多份,session不同步问题
  • 不同服务,session不能共享问题
1.3.2. Session共享问题解决
1.3.2.1. session复制

1.3.2.2. 客户端存储

1.3.2.3. hash一致性

1.3.2.4. 统一存储

1.3.2.5. 不同服务,子域session共享

1.3.3. SpringSession整合redis

通过SpringSession修改session的作用域

1.3.3.1. 环境搭建

gulimall-auth-server模块

pom导入依赖

<dependency>
  <groupId>org.springframework.session</groupId>
  <artifactId>spring-session-data-redis</artifactId>
</dependency>

修改apllication.properties配置

spring.session.store-type=redis

主配置类添加注解@EnableRedisHttpSession

修改“com.cwh.gulimall.auth.GulimallAuthServerApplication”类,代码如下:

@EnableRedisHttpSession
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class GulimallAuthServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(GulimallAuthServerApplication.class, args);
    }
}
1.3.3.2. 自定义配置
1.3.4. SpringSession核心原理

核心原理:

1)、@EnableRedisHttpSession导入RedisHttpSessionConfiguration.class配置
1、给容器中添加了一个组件
SessionRepository=》》》 【RedisIndexedSessionRepository】=>redis操作session.session的增删改查的封装类
2、SessionRepositoryFilter=》Filter: session存储过滤器,每个请求过来都必须经过filter
1、创建的时候,就自动从容器中获取到了SessionRepository:
2、原生的request,response都被包装。SessionRepositoryRequestWrapper,SessionRepositoryResponseWrapper
3、以后获取session.request.getSession()
4、wrapperedRequest.getSession();===>SressionRepository中获取到

自动延期。redis中的数据也是有过期时间的

装饰者模式 - SessionRepositoryFilter

  • 原生的获取session时是通过HttpServletRequest获取的
  • 这里对request进行包装,并且重写了包装request的getSession()方法
1.3.5. 页面调整
1.3.5.1. 只要登录成功,缓存有用户数据,再点击登录链接,直接调转到首页;把GulimallWebConfig登录页的映射注释掉

修改“com.cwh.gulimall.auth.controller.LoginController”类,代码如下:

@GetMapping("/login.html")
public String loginPage(HttpSession session){
Object attribute = session.getAttribute(AuthServerConstant.LOGIN_USER);
if (attribute == null) {
    //没登录
    return "login";
} else{
    return "redirect:http://gulimall.com";
}
}
1.3.5.2. 账号密码方式登录也要显示用户名

正常登录也要显示用户名,返回时也要给他放入用户信息

修改“com.cwh.gulimall.auth.controller.LoginController”类,代码如下:

@PostMapping("/login")
public String login(UserLoginVo vo, RedirectAttributes redirectAttributes, HttpSession session) {
    log.info("登录请求参数:{}", JSON.toJSONString(vo));
    //远程登录
    R r = memberFeignService.login(vo);
    if (r.getCode() == 0) {
        MemberResponseVO loginUser = r.getData(new TypeReference<MemberResponseVO>() {
        });
        // 成功放到session中
        session.setAttribute(AuthServerConstant.LOGIN_USER, loginUser);
        return "redirect:http://gulimall.com";
    } else {
        Map<String, String> errors = new HashMap<>();
        errors.put("msg", r.getData("msg", new TypeReference<String>() {
        }));
        redirectAttributes.addFlashAttribute("errors", errors);
        return "redirect:http://auth.gulimall.com/login.html";
    }
}
1.3.5.3. 只要登陆成功每个页面都显示用户名

gulimall-search服务页面显示用户名,需要先搭建好SpringSession环境

导入依赖

     <!--整合SpringSession完成session共享问题-->
    <dependency>
        <groupId>org.springframework.session</groupId>

        <artifactId>spring-session-data-redis</artifactId>

    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-data-redis</artifactId>

    </dependency>

修改配置

#配置redis
spring.redis.host=192.168.119.127
spring.redis.port=6379
#session存储格式
spring.session.store-type=redis

加注解

添加SpringSession配置类

@Configuration
public class GulimallSessionConfig {
    @Bean
    public CookieSerializer cookieSerializer(){
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        cookieSerializer.setDomainName("gulimall.com");
        cookieSerializer.setCookieName("GULISESSION");
        return cookieSerializer;
    }

    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer(){
        return new GenericJackson2JsonRedisSerializer();
    }
}

1.4. SSO 单点登录

Single Sign On 一处登陆、处处可用

前置概念

1 )、单点登录业务介绍

早期单一服务器,用户认证。

缺点:单点性能压力,无法扩展

分布式,SSO(single sign on)模式

多系统

解决 :

  • 用户身份信息独立管理,更好的分布式管理。
  • 可以自己扩展安全策略
  • 跨域不是问题

缺点:

  • 认证服务器访问压力较大。

gitee参考项目:xxl-sso: 一个分布式单点登录框架。只需要登录一次就可以访问所有相互信任的应用系统。 拥有"轻量级、分布式、跨域、Cookie+Token均支持、Web+APP均支持"等特性;。现已开放源代码,开箱即用。

xxl-sso流程:

  • /xxl-sso-server 登录服务器 8080 ssoserver.com
  • /xxl-sso-web-sample-springboot 项目1 8081 client1.com
  • /xxl-sso-web-sample-springboot 项目2 8082 client2.com
#----------sso----------
127.0.0.1 ssoserver.com
127.0.0.1 client1.com
127.0.0.1 client2.com

核心:三个系统即使域名不一样,想办法给三个系统同步同一个用户的票据;

1)、中央认证服务器;ssoserver.com

2)、其他系统,想要登录去ssoserver.com登录,登录成功跳转回来

3)、只要有一个登录,其他都不用登录

4)、全系统统一一个sso-sessionid;所有系统可能域名都不相同

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

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

相关文章

价值5000元完整版GOD引擎手机客户端三端引擎源码 编译完整版

5000元完整版GOD引擎手机客户端三端引擎源码 支持三端互通&#xff1a;电脑端&#xff0c;安卓端&#xff0c;苹果端 GOD引擎全套源码及手游客户端源码&#xff08;苍穹引擎源码及修改教程&#xff09; 服务端代码为Delphir&#xff0c;手游客户端代码为cocos2dx的&#xff08;…

DAMA数据管理知识体系(第14章 大数据和数据科学)

课本内容 14.1 引言 概要 从数据中探究、研发预测模型、机器学习模型、规范性模型和分析方法并将研发结果进行部署供相关方分析的人&#xff0c;被称为数据科学家业务驱动 期望抓住从多种流程生成的数据集中发现的商机&#xff0c;是提升一个组织大数据和数据科学能力的最大业务…

论文阅读(十二):Attention is All You Need

文章目录 一、循环神经网络1.1RNN模型1.1.1RNN模型简介1.1.2RNN基本结构1.1.3权重共享机制1.1.4RNN局限性&#xff1a;长期依赖问题与梯度消失 1.2LSTM模型1.2.1LSTM核心思想1.2.2遗忘门1.2.3输入门1.2.4更新细胞状态1.2.5输出门1.2.6参数更新 二、Seq2Seq机制2.1RNN结构的局限…

react 知识点汇总(非常全面)

React 是一个用于构建用户界面的 JavaScript 库&#xff0c;由 Facebook 开发并维护。它的核心理念是“组件化”&#xff0c;即将用户界面拆分为可重用的组件。 React 的组件通常使用 JSX&#xff08;JavaScript XML&#xff09;。JSX 是一种 JavaScript 语法扩展&#xff0c;…

house_of_muney

house_of_muney 首先介绍一下house of muney 这个利用原理&#xff1a; 在了解过_dl_runtime_resolve的前提下&#xff0c;当程序保护开了延迟绑定的时候&#xff0c;程序第一次调用相关函数的时候会执行下面的命令 push n push ModuleID jmp _dl_runtime_resolve 这里的n…

OCR+PDF解析配套前端工具开源详解!

目录 一、项目简介 TextIn为相关领域的前端开发提供了优秀的范本。 目前项目已在Github上开源&#xff01; 二、性能特色 三、安装使用 安装依赖启动项目脚本命令项目结构 四、效果展示 面对日常生活和工作中常见的OCR识别、PDF解析、翻译、校对等场景&#xff0c;配套的…

洛谷P5648

洛谷P5648 这题花了很长时间&#xff0c;是在线段树题单里找到的&#xff08; &#xff09;。有线段树做法&#xff0c;但是我感觉可能比倍增做法更难看懂。以后有空再看看吧。感觉线段树现在只会板子题&#xff0c;绿稍微难点可能就不会。 花了很久时间之后&#xff0c;就觉得…

打造直播美颜平台的关键技术:视频美颜SDK的深度解析

本篇文章&#xff0c;小编将深入解析视频美颜SDK的关键技术&#xff0c;探讨其在打造直播美颜平台中的作用。 一、视频美颜SDK的定义与功能 视频美颜SDK是一套专门为实时视频处理而设计的软件开发工具包。其主要功能包括人脸检测、肤色美化、瑕疵修复、虚化背景、实时滤镜等。…

Python对PDF文件的合并操作

在处理 PDF 文件时&#xff0c;合并多个 PDF 文件为一个单一文件或者将某个单一文件插入某个PDF文件是一个常见的需求。Python 提供了多种库来实现这一功能&#xff0c;其中 PyPDF2 是一个非常流行的选择。该库提供了简单易用的接口&#xff0c;包括 merge() 方法&#xff0c;可…

CRE6281B1 (宽VCC:8-45V PWM电源芯片)

CRE6281B1 是一款外驱功率管的高度集成的电流型PWM 控制 IC&#xff0c;为高性能、低待机功率、低成本、高效率的隔离型反激式开关电源控制器。在满载时&#xff0c;CRE6281B1工作在固定频率(65kHz)模式。在负载较低时&#xff0c;采用节能模式&#xff0c;实现较高的功率转换效…

关于Allegro导出Gerber时的槽孔问题

注意点一&#xff1a; 如果设计的板子中有 槽孔和通孔(俗称圆孔)&#xff0c;不仅要NC Drill, 还要 NC Route allegro导出的槽孔文件后缀是 .rou 圆型孔后缀 是 .drl &#xff0c;出gerber时需要看下是否有该文件。 注意点二&#xff1a; 导出钻孔文件时&#xff0c;设置参…

Hi3061M开发板——系统时钟频率

这里写目录标题 前言MCU时钟介绍PLLCRG_ConfigPLL时钟配置另附完整系统时钟结构图 前言 Hi3061M使用过程中&#xff0c;AD和APT输出&#xff0c;都需要考虑到时钟频率&#xff0c;特别是APT&#xff0c;关系到PWM的输出频率。于是就研究了下相关的时钟。 MCU时钟介绍 MCU共有…

22.1 K8S之KubeSphere实现中间件高可用集群

22.1 K8S之KubeSphere实现中间件高可用集群 一. 章节概述二. WordPress1. WordPress 简介---------------------------------------------------------------------------------------------------一. 章节概述 二. WordPress 1. WordPress 简介 创建并部署 WordPress

MySQL 数据库的性能优化方法方法有哪些?

MySQL 数据库的性能优化方法方法有哪些&#xff1f; 从开发角度来看&#xff0c;一般可以从 SQL 和库表设计两部分优化性能。 SQL 优化 根据慢sql日志&#xff0c;找出需要优化的一些sql语句。 常见优化方向&#xff1a; 避免select *&#xff0c;只查询必要的字段&#x…

62 加密算法

62 加密算法 三种加密算法分类&#xff1a; 对称加密&#xff1a;密钥只有一个&#xff0c;解密、解密都是这个密码&#xff0c;加解密速度快&#xff0c;典型的对称加密有DES、AES、RC4等非对称加密&#xff1a;密钥成对出现&#xff0c;分别为公钥和私钥&#xff0c;从公钥…

sass学习笔记(1.0)

1.使用变量 sass可以像声明变量那样进行使用&#xff0c;这样同样的样式&#xff0c;就可以使用相同的变量来提高复用。 语法为&#xff1a;$ 变量名 在界面中也可以正常的显示 当然了&#xff0c;变量之间也可以相互引用&#xff0c;比如下面 div{$_color: #d45387;$BgColo…

kibana 删除es指定数据,不是删除索引

1 查询条件查询出满足条件的数据 GET /order_header_idx_202410/_search {"from":0,"size":10,"query":{"bool":{"filter":[{"term":{"oh_tenantId":{"value":"0211000001",&…

NeuVector部署、使用与原理分析

文章目录 前言1、概述2、安装与使用2.1、安装方法2.1.1、部署NeuVector前的准备工作2.1.1.1 扩容系统交换空间2.1.1.2 Kubernetes单机部署2.1.1.2.1 部署Docker2.1.1.2.2 部署Kubectl2.1.1.2.3 部署Minikube 2.1.1.3 Helm部署 2.1.2、使用Helm部署NeuVector 2.2、使用方法2.2.1…

YOLOv5改进——添加SimAM注意力机制

目录 一、SimAM注意力机制核心代码 二、修改common.py 三、修改yolo.py ​三、建立yaml文件 四、验证 一、SimAM注意力机制核心代码 在models文件夹下新建modules文件夹&#xff0c;在modules文件夹下新建一个py文件。这里为simam.py。复制以下代码到文件里面。 import…

Mysql中创建用户并设置任何主机连接

Mysql中创建用户并设置任何主机连接 文章目录 Mysql中创建用户并设置任何主机连接背景解决方式 背景 在linux上安装mysql,默认用户是root,但是用navicat连接不了,必须要用ssh隧道连接,现在想用任何主机只要输入账号密码之后就可以连接 解决方式 #创建一个指定用户和IP链接的用…