Consul+Ocelot搭建微服务实践--IdentityServer集成

2023-05-16

文章目录

  • 1、IdentityServer介绍
  • 2、建立IdentityServer
    • 2.1 安装IdentityServer4
    • 2.2 定义配置中心
      • 2.2.1 定义Client
      • 2.2.2 定义ApiResource
      • 2.2.3定义IdentityResource
  • 3、配置IdentityServer到Ocelot中去
    • 3.1 添加配置文件
    • 3.2 进行测试
  • 4、总结
  • 5 、附录

本篇幅所涉及的内容比较多,请园友有耐心的品味下去。

1、IdentityServer介绍

IdentityServer4 是asp.netcore 的OpenID Connect和OAuth 2.0框架。官方文档:http://docs.identityserver.io/en/latest/
我主要进行对自己所做的进行总结,不会介绍很多的理论类容。

2、建立IdentityServer

2.1 安装IdentityServer4

可以使用PS进行命令安装: Install-Package IdentityServer4。也可以在Nuget管理中心进行搜索安装。

2.2 定义配置中心

网上很多都是使用的TestUser进行的测试,我这个案例中使用sqlserver持久化进行验证,对于用户这块我后面详细介绍。(要是觉得麻烦那么也可以使用TestUser和)

2.2.1 定义Client

可以查看 官方文档–Client 进行了解Client相关知识。

public class InMemoryConfiguration
{
	public static IEnumerable<Client> GetAllClients()
	{
		return new[]
		{
		//采用密码模式
		new Client
		 {
		     ClientId = "api.service1",
		     ClientSecrets = new [] { new Secret("secret".Sha256()) },
		     AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
		     AllowedScopes = new [] {
		         "service1",
		     },
		     //支持刷新token
		     AllowOfflineAccess=true,
		     //toke过期时间。默认一小时
		     //AccessTokenLifetime=60,
		     //滑动刷新token的时间。默认一天。
		     //SlidingRefreshTokenLifetime=60,
		     //刷新token的模式,固定刷新时间和滑动刷新时间
		     //RefreshTokenExpiration=TokenExpiration.Sliding,                    
		     //详情文档:https://identityserver4-zh-cn.readthedocs.io/zh_CN/release/topics/refresh_tokens.html
		 },
		//采用客户端模式
		 new Client
		 {
		     ClientId = "api.service2",
		     ClientSecrets = new [] { new Secret("secret".Sha256()) },
		     AllowedGrantTypes = GrantTypes.ClientCredentials,
		     AllowedScopes = new [] {
		         "service2",
		     },
		 }
		};
	}
}

2.2.2 定义ApiResource

可以查看 官方文档–ApiResouce 进行了解ApiResouce相关知识。

public class InMemoryConfiguration
{
	public static IEnumerable<ApiResource> GetAllResources()
	{
	    return new[]
	    {
	        //向Cliam中添加Role、Email。这样在获取HttpContext.User.Cliam时才能获取到role、email
	        new ApiResource("service1", "微服务架构设计,Service1",new List<string>{
	            JwtClaimTypes.Role,
	            JwtClaimTypes.Email,
	        }),
	        new ApiResource("service2", "微服务架构设计,Service2",new List<string>{
	            JwtClaimTypes.Role,
	            JwtClaimTypes.Email,
	        })
	    };
	}
}

2.2.3定义IdentityResource

可以查看 官方文档–IdentityResource 进行了解IdentityResource相关知识。

public class InMemoryConfiguration
{
	public static IEnumerable<IdentityResource> GetIdentityResources()
	 {
	     //定义支持的资源类型。SuportScope的类型
	     return new List<IdentityResource>
	     {
	         new IdentityResources.OpenId(),
	         new IdentityResources.Profile(),
	         new IdentityResources.Email()
	     };
	 }
}

使用UseIdentityServer先考虑几个问题。

1) 那些API可以使用AuthorizationServer
2) 那些Client可以使用AuthorizationServer
3) 那些User可以使用AuthorizationServer

既然定义了这些资源内容那么就要添加到IdentityServer中去。

在ConfigureServices中添加内容:

#region identityserver4           
//添加中间件
services.AddIdentityServer()
    .AddSigningCredential(new X509Certificate2(
        Path.Combine(Directory.GetCurrentDirectory(),Configuration["Credential:Path"]),
        Configuration["Credential:Password"],
        X509KeyStorageFlags.MachineKeySet))
    .AddInMemoryClients(InMemoryConfiguration.GetAllClients())
    .AddInMemoryApiResources(InMemoryConfiguration.GetAllResources())
    .AddResourceOwnerValidator<CustomResourceOwnerPasswordValidator>()
    .AddProfileService<CustomProfileService>()
    .AddCorsPolicyService<CorsPolicyService>();
#endregion

在Configure中使用IdentityServer

app.UseIdentityServer();

对以上添加的内容进行解释

  1. 在实际的项目中肯定会使用自己的证书的,在这里使用AddSigningCredential添加证书。IdentityServer也友好的提供了开发者使用证书,使用AddDeveloperSigningCredential进行添加。

    使用openssl工具生成证书。

    下载地址通过我的百度云盘进行下载,因为本地直接下载可能很慢甚至可能下载不了。
    链接:https://pan.baidu.com/s/1-kf3T7iOO3PuzFRag_atZQ
    提取码:q79u

    1.1. 使用openssl命令进行证书下载

    openssl req -newkey rsa:2048 -nodes -keyout auth.center.key -x509 -days 365 -out auth.center.cer

    下面将生成的证书和Key封装成一个文件,以便IdentityServer可以使用它们去正确地签名tokens
    openssl pkcs12 -export -in auth.center.cer -inkey cas.clientservice.key -out auth.center.pfx

    最终生成的目录结构:
    在这里插入图片描述
    1.2 然后将生成的文件拷贝到项目中去,并在appsetting.json文件中配置路径密码(上面生成证书的时候输入的密码)。

    {
      "DBConnStr": "Server=.;DataBase=Study.Microservices.Information;User=sa;Password=123456",
      "Credential": {
        "Path": "cert\\IDS4.pfx",
        "Password": "cy"
      },
      "Logging": {
        "LogLevel": {
          "Default": "Warning"
        }
      },
      "AllowedHosts": "*"
    }
    

    最后就将所生成的证书配置到AddSigningCredential中去,详情请看上面贴的配置。

  2. 使用AddResourceOwnerValidator添加自定义验证。

    2.1 继承IResourceOwnerPasswordValidator实现Task ValidateAsync(ResourceOwnerPasswordValidationContext context); 方法进行自定义验证。

    public class CustomResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
    {
        private readonly ISystemClock _clock;
        private readonly IUserApplicationService _users;
        public CustomResourceOwnerPasswordValidator(ISystemClock clock,
            IUserApplicationService users)
        {
            _clock = clock;
            _users = users;
        }
        public  Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
        {
            if (_users.ValidateCredentials(context.UserName, context.Password))
            {
                var user = _users.FindUserByAccount(context.UserName);
    
                //验证通过返回结果 
                //subjectId 为用户唯一标识 一般为用户id
                //authenticationMethod 描述自定义授权类型的认证方法 
                //authTime 授权时间
                //claims 需要返回的用户身份信息单元 此处应该根据我们从数据库读取到的用户信息 
                //添加Claims 如果是从数据库中读取角色信息,那么我们应该在此处添加 此处只返回必要的Claim
                context.Result = new GrantValidationResult(
                    user.Id ?? throw new ArgumentException("Subject ID not set", nameof(user.Id)),
                    OidcConstants.AuthenticationMethods.Password, _clock.UtcNow.UtcDateTime,
                    claims: GetClaims(user));
            }
            else
            {
                //验证失败
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "invalid custom credential");
            }
            return Task.CompletedTask;
        }
        /// <summary>
        /// 添加自定义Claim
        /// </summary>
        /// <param name="claims"></param>
        /// <returns></returns>
        private ICollection<Claim> GetClaims(UserInfo user)
        {
            return new Claim[]{
                new Claim(JwtClaimTypes.Id,user.Id),
                new Claim(JwtClaimTypes.Name,user.Account)
            };
        }
    }
    

    2.2 用户相关操作接口IUserApplicationService

    public interface IUserApplicationService
    {
        /// <summary>
        /// 通过用户名查到用户信息
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <returns></returns>
        UserInfo FindUserByAccount(string userName);
        /// <summary>
        /// 判断用户是否可以登录
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <param name="password">密码</param>
        /// <returns></returns>
        bool ValidateCredentials(string userName, string password);
    
        /// <summary>
        /// 通过用户id查找用户信息
        /// </summary>
        /// <param name="id">用户id</param>
        /// <returns></returns>
        UserInfo FindBySubjectId(string id);
    }
    

    2.3 用户实体类

    [Table("User")]
    public class UserInfo
     {
         [Key]
         public string Id { get;  set; }
    
         public string Account { get;  set; }
    
         public bool IsActive { get; set; }
         public string Password { get; internal set; }
     }
    

    2.3 用户相关操作实现UserApplicationService

    public class UserApplicationService : IUserApplicationService
    {       
        public UserInfo FindBySubjectId(string id)
        {
            using (var db=new UserDbContext())
            {
                return db.Users.FirstOrDefault(u => u.Id == id & u.IsActive);
            }
        }
    
        public UserInfo FindUserByAccount(string userName)
        {
            using (var db = new UserDbContext())
            {
                return db.Users.FirstOrDefault(u => u.Account == userName & u.IsActive);
            }
        }
    
        public bool ValidateCredentials(string userName, string password)
        {
            using (var db = new UserDbContext())
            {
                return db.Users.Where(u => u.Account == userName
                & u.Password==password
                & u.IsActive).Count()>0;
            }
        }
    }
    

    2.4 从上面的实现类中可以看出采用的是EF,那么下面我将简单快速的将Migration的使用以及EF Core的使用进行介绍。

    1) 安装Microsoft.EntityFrameworkCore.SqlServer
    2)添加UserDbContext

    public class UserDbContext : DbContext
      {
          public UserDbContext()
          {
    
          }
          public DbSet<UserInfo> Users { get; set; }
    
          protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
          {
              base.OnConfiguring(optionsBuilder);
              var build = new ConfigurationBuilder()
                      .SetBasePath(System.IO.Directory.GetCurrentDirectory())
                      .AddJsonFile("appsettings.json", false, true)
                      .Build();
              optionsBuilder.UseSqlServer(build["DBConnStr"]);
          }
      }
    

    DBConnStr 是配置文件中配置的,配置文件件贴在了证书介绍区域。

    3)使用Migration将User添加到数据库中去。

    执行 Add-Migration 初始化用户 命令添加相关修改到Migrations中去。

    在这里插入图片描述

    最终会生成一个Migrations目录结构,后面对模型进行调整添加修改等等操作都会记录到这个文件中去。

    在这里插入图片描述

    执行 update-database –verbose 更新数据库

    最终生成数据库结构:
    在这里插入图片描述
    为了测试我将User表中添加了一条admin/admin的数据,为了后面进行测试。

  3. 使用AddProfileService添加自定义Profile装载Claim信息

    采用自定义验证都要结合AddProfileService来使用,通过AddProfileService来装载前面定义的CustomResourceOwnerPasswordValidatorClaim信息。然后在使用的时候直接调用User.Claims就能看到配置的自定义Claim信息了。

    /// <summary>
    /// 采用自定义profile来装载Claim信息
    /// </summary>
    public class CustomProfileService : IProfileService
    {
        /// <summary>
        /// The logger
        /// </summary>
        protected readonly ILogger Logger;
        private readonly IUserApplicationService _users;
        /// <summary>
        /// Initializes a new instance of the <see cref="CustomProfileService"/> class.
        /// </summary>
        /// <param name="logger">The logger.</param>
        public CustomProfileService(ILogger<CustomProfileService> logger,IUserApplicationService users)
        {
            Logger = logger;
            _users = users;
        }
    
        /// <summary>
        /// 只要有关用户的身份信息单元被请求(例如在令牌创建期间或通过用户信息终点),就会调用此方法
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        public virtual Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            context.LogProfileRequest(Logger);
            //判断是否有请求Claim信息
            if (context.RequestedClaimTypes.Any())
            {
                //根据用户唯一标识查找用户信息
                var user = _users.FindBySubjectId(context.Subject.GetSubjectId());
                if (user != null)
                {
                    //调用此方法以后内部会进行过滤,只将用户请求的Claim加入到 context.IssuedClaims 集合中
                    context.IssuedClaims = context.Subject.Claims.ToList();
                }
            }
            context.LogIssuedClaims(Logger);
            return Task.CompletedTask;
        }
        /// <summary>
        /// 验证用户是否有效 例如:token创建或者验证
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        public virtual Task IsActiveAsync(IsActiveContext context)
        {
            Logger.LogDebug("IsActive called from: {caller}", context.Caller);
            var user = _users.FindBySubjectId(context.Subject.GetSubjectId());
            context.IsActive = user?.IsActive == true;
            return Task.CompletedTask;
        }
    }
    
  4. 使用AddCorsPolicyService来配置跨域

    IdentityServer提供了DefaultCorsPolicyService默认跨域类。我这里使用自定义的CorsPolicyService来处理跨域,使用自定的跨域处理类只需要实现ICorsPolicyService中的Task IsOriginAllowedAsync(string origin) 即可。

    为了测试我这里支架返回true允许所有,在实际中肯定是不行的,需要业务场景去配置相关origin。

    private class CorsPolicyService : ICorsPolicyService
    {
        public Task<bool> IsOriginAllowedAsync(string origin)
        {
            return Task.FromResult(true);
        }
    }     
    

3、配置IdentityServer到Ocelot中去

上面啰里啰嗦的说了那么多,也是怕园友们会学的糊里糊涂,因为我看文章都是这么过来的,学个东西要看很多文章甚至要看很多遍才能够理解清楚。

3.1 添加配置文件

不明白的可以看前面两篇文章
Consul+Ocelot搭建微服务实践–初探路由
Consul+Ocelot搭建微服务实践–负载均衡

{
  "ReRoutes": [
    //identityserver4  token
    {
      "DownstreamPathTemplate": "/connect/token",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": "5001"
        }
      ],
      "UpstreamPathTemplate": "/auth/token",
      "UpstreamHttpMethod": [ "Post" ]
    }
  ]
}

3.2 进行测试

终于可以看到你们心中怀念已久的token了。
设置Body的内容,设置的内容也是前面InMemoryConfiguration所配置的内容。

在这里插入图片描述
修改Body 中的值进行测试:

特意将secret的值进行修改进行测试。

在这里插入图片描述
IdentiyServer的日志分析:
在这里插入图片描述

4、总结

大部分类容都是围绕着IdentityServer的展开的,这里会为下文做一个铺垫,后面使用Ocelot集中授权认证的时候会用到。

真心的发现总结一块内容是多么的花时间,写这点东西不知不觉花了一个多小时,大多数都是记录的我自己的测试中所运用到的东西,还没有很啰里啰嗦。咋一看时间不知不觉已经十二点过了在这里插入图片描述重庆最近的雨水是真心多,从周五晚上到现在一直没有停过,并且还下的很大,敲着代码听着雨滴敲打在我家雨棚上面的声音真好听,至少还有它们陪着我。
慢慢自己将前面学的东西总结下来想想还是蛮有成就感的,心中有那么一丁点的欣慰。能够得到园子里面的园友们支持我会很高兴!

5 、附录

本系列其他文档:

  • Consul+Ocelot搭建微服务实践–初探路由
  • Consul+Ocelot搭建微服务实践–负载均衡
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Consul+Ocelot搭建微服务实践--IdentityServer集成 的相关文章

  • Consul+Ocelot搭建微服务实践--IdentityServer集成

    文章目录 1 IdentityServer介绍2 建立IdentityServer2 1 安装IdentityServer42 2 定义配置中心2 2 1 定义Client2 2 2 定义ApiResource2 2 3定义Identity
  • ocelot+IdentityServer认证

    IdentityServer4 IdentityServer4是用于ASP NET Core的OpenID Connect和OAuth 2 0框架 具体大家可以自己搜索 xff0c 网上很多 我不想写的就推荐别人的 IdentityServ
  • docker-compose搭建consul集群环境

    目录 consul基本概念 server模式启动的命令行参数 使用docker compose来搭建如下的consul集群环境 编辑docker compose yml文件 启动服务 常用命令 注册配置中心例子 yml KV访问的例子 co
  • consul配置

    配置文件 1 除了命令行选项之外 xff0c 配置还可以放入文件中 在某些情况下 xff0c 这可能更容易 xff0c 例如使用配置管理系统配置Consul时 2 配置文件是JSON格式 3 配置文件不仅用于设置代理 xff0c 还用于提供
  • windows 上 consul

    本机开发模式 consul官网 本机开发者模式 consul exe agent dev 局域网 consul exe agent dev client 0 0 0 0
  • SpringCloud(五)Consul服务注册与发现

    SpringCloud xff08 四 xff09 zookeeper介绍及原理 xff1a https blog csdn net weixin 45606067 article details 108538357 Consul简介 是什
  • Docker consul 容器服务自动发现和更新

    目录 一 什么是服务注册与发现 二 Docker consul集群 1 Docker consul consul提供的一些关键特性 2 registrator 3 Consul template 三 Docker consul实现过程 以配
  • SpringCloud使用Consul作为服务注册发现中心

    本篇文章主要记录SpringCloud使用Consul作为服务注册发现中心 通过服务提供者和消费者为例 来真正掌握Consul注册中心 目录 一 前言 二 搭建服务提供者 1 创建cloud provider payment8004项目 2
  • 解密5G新基建浪潮下的“智慧杆塔”缘何火热

    文章版权所有 未经授权请勿转载或使用 关于智慧杆塔并不算一个新概念或新领域 从早期的智慧路灯 到加载少量城市传感器或电子广告牌的智慧灯杆等 都属于智慧杆塔的早期概念或雏形 但近来笔者通过走访灯杆生产厂商发现 行业终于盼来了爆发的春天 智慧杆
  • 可以同情弱者,别同情弱势!

    大家好 我是北妈 0 最近北妈在重刷 天道 里面提到了一个强势文化 弱势文化的概念 我觉得对生活和职场 感情都有些指导作用 我看影评和各种文章讨论这个的概念比较多 毕竟大家都喜欢谈格局 强弱 今天讨论下如何成为强者 强者是不是应该鄙视弱者
  • Mysql读写锁保姆级图文教程

    准备 创建 mylock 表 CREATE TABLE mylock id int 11 NOT NULL AUTO INCREMENT name varchar 20 DEFAULT NULL PRIMARY KEY id ENGINE
  • 如何引导机器?如何面临人机结合?《​人工智能与人类未来》

    微信公众号 乐生活与爱 公众号曾转载过蔡恒进教授的奇文 意识如何演化 机器何时有自我意识 附着与隧通 心智的工作模式 值得反复也读 我上周听了由北京大学博古睿研究中心 中国人民大学哲学院 中国人民大学哲学与认知科学交叉平台 服务器艺术联合主
  • 在微软工作365天,还你一个我眼中更加真实的微软

    去年12月28日 我正式成为了微软中国的一名员工 今天又是12月28日 不知不觉我已经在这里工作365天了 其实在入职100天的时候我就写过一篇关于微软的文章 详见 在微软工作100天 谈谈我眼中的微软 但那个时候毕竟待的时间还比较短 所以
  • .net 配置网关(使用Ocelot)

    本文演示一个最简单的demo 来模拟如何通过网关来访问服务 而不是直接访问服务 创建三个asp net core web api项目 一个作为网关 两个作为服务 分别配置项目的访问路径 网关的项目使用https localhost 5001
  • 4.Docker--Consul

    Docker Consul 引言 Consul是HashiCorp公司推出的开源工具 Consul由Go语言开发 部署起来非常容易 只需要极少的可执行程序和配置文件 具有绿色 轻量级的特点 Consul是分布式的 高可用的 可横向扩展的用于
  • 【SpringCloud】整合Consul+OpenFeign实现微服务+负载均衡(下)

    一 代码 由于篇幅有限 代码见上一篇文章 https blog csdn net forest long article details 129287941 分别启动Consul Service provider Service consu
  • 无法在 spring-boot 应用程序中从 Consul 读取配置

    我正在创建一个Spring Boot应用程序 它将读取诸如数据库属性之类的配置Consul 但我无法使用我的应用程序从 Consul 读取键值 以下是我正在尝试做的事情 pom xml
  • API网关上的数据聚合

    我正在研究微服务架构 我想聚合来自两个微服务的数据 例如 Frontend 调用 API Gateway API Gateway 调用两个微服务 Customer 和 Order 微服务 客户微服务返回客户详细信息 订单微服务返回客户订购的
  • 如何使用 Consul 中定义的默认值在 Terraform 中定义可选变量

    我有一个 Terraform 脚本 其中包含一些从 Consul 填充的变量 我想在两种不同的场景中使用这个脚本 场景 1 使用 Consul 的默认值一切正常 场景 2 我需要覆盖一些变量 我检查了 Terraform 文档 发现我无法使
  • 领事注销“失败”服务

    我有 Consul 在 Consul v0 5 2 版本上运行 服务在 Mesos 中运行 服务不断从一台服务器转移到另一台服务器 有没有办法取消领事中处于 失败 状态的服务 我可以使用此curl 获取处于失败状态的服务列表 curl ht

随机推荐

  • Cmake系列(三) 在 CMakeLists.txt 引入第三方so库

    将 so 库和头文件拷贝到对应的目录 app src main jniLibs arm libxxx so 修改 CMakeLists txt 文件 第三方so库 这里和之前在第二步中介绍的创建一个新的原生库类似 xff0c 区别在于最后一
  • .net core MemoryCache(本机缓存)过期策略

    过期策略 1 1 永不过期 xff1a 永远不会过期 1 2 设置绝对过期时间点 xff1a 到期后就失效 1 3 设置过期滑动窗口 xff1a 只要在窗口期内访问 xff0c 它的过期时间就一直向后顺延一个窗口长度 1 4 滑动窗口 43
  • Windows asar工具安装使用与破解StarUml

    目录 安装nodejs 使用npm安装asar asar的压缩与解压 破解StarUml windows要破解StarUml xff0c 需要用到asar进行解压与打包 asar可以借助npm来安装 xff0c mac可以用homebrew
  • logcat中 读取垃圾回收消息

    目录 Dalvik 日志消息 ART 日志消息 有时 xff0c 发生垃圾回收事件时 xff0c 相应消息会输出到 Logcat 中 Dalvik 日志消息 在 Dalvik xff08 而不是 ART xff09 中 xff0c 每个 G
  • arm64-v8a、armeabi-v7a、armeabi、x86 abiFilters 详解

    abiFilters的作用 在app的gradle的defaultConfig里面加上如下 ndk abiFilters 34 armeabi v7a 34 指定要ndk需要兼容的架构 这样其他依赖包里mips x86 armeabi ar
  • Linux shell

    目录 shell 脚本 shell 概述 shell 分类 shell 语法 shell 脚本的定义与执行 自定义变量 环境变量 预设变量 脚本变量的特殊用法 条件测试语句 gt 文件 条件测试语句 gt 字符串 条件测试语句 gt 数字
  • Linux > mmap

    目录 mmap 概念 使用 函数声明 mmap 概念 mmap 将 一个文件或者其它对象 映射到 进程的地址空间 实现 磁盘地址 和进程 虚拟的虚拟地址 的一一对应关系 通过mmap 系统调用 xff0c 我们可以 实现共享内存或者普通文件
  • C++ > STL之算法

    目录 函数对象 谓词 一元谓词 二元谓词 内建函数对象 适配器 算法概述 常用遍历算法 for each 遍历算法 transform 算法 常用查找算法 find 算法 find if 算法 adjacent find 算法 binary
  • 性能优化 启动黑白屏优化

    启动黑白屏优化 前言 这是Google设计者为了让用户体会到点击图标后立马就有响应 xff0c 而让App创建的过程中先展示一个空白窗口 正是这个设计 xff0c 我们在点击App应用图标之后 xff0c 会看到一段时间的空白屏幕 xff0
  • 解决android studio Could not GET 'https://dl.google.com/dl/android/maven2

    解决android studio Could not GET 39 https dl google com dl android maven2 1 http proxy 选择 No proxy 模式 2 修改gradle配置文件 找到C U
  • Unable to add window — token android.os.BinderProxy is not valid; is your activity running?

    现象是 xff1a 第一次显示Dialog正常显示 xff0c 但按了返回键后 xff0c 再次进入程序显示Dialog时就会报错 原因 xff1a 我把 对Dialog义为了static 变量 导致退出程序后 xff0c 再次进入来显示D
  • Visual Studio 新建一个Win32控制台项目

    1 点击 文件 新建 项目 2 选好Win32控制台项目点击确定 3 点击击下一步 4 勾选好项目程序设置后点击完成 5 点击 本地 Windows 调试器即可调试程序
  • 安装CDC drivers 失败原因,记录关键点

    1 驱动版本不对 xff0c 因为CDC drivers 主要调用的是usbser sys 文件 xff0c 需要查看你的c windows system32 drivers下是否有该文件 2 驱动对了 xff0c 但是安装过程中一直提示找
  • Ubuntu 运行文件时,出现 Permission denied

    在Ubuntu下 xff0c 执行sh文件时提示下面信息 xff1a bash xx sh Permission denied 可以尝试以下方法解决 xff1a chmod 777 xx sh 执行其他类型的文件出错时 xff0c 也可以此
  • update.app格式解压工具-ROM定制开发教程

    Github分享工具地址 xff1a https github com Loren Yi update app 使用教程 xff1a 下载huawei unpack exe 到本地目录 讲华为 UPDATE APP放至同一路径 将 UPDA
  • mysql时间和本地时间相差13个小时

    原文地址 https www xiegaosheng com post view id 61 73 mysql时间和本地时间相差13个小时 作者 谢高升 发布 2017 12 15 浏览 0次 mysql时间和本地时间相差13个小时 修改l
  • 美团笔试题(2018.10.09)

    逻辑题20个要快点做 xff0c 然后30个选择考的东西比较多 编程两个 优惠券 有一个满x减的优惠券 xff0c 一共n个商品 xff0c 每个只能选择一次 xff0c 求能使用优惠券的最小价格 就是求n个数选任意几个加起来最接近x且大于
  • AndroidStudio gradle 编译发现阿里云镜像找不到对应jar包https://maven.aliyun.com/nexus/content/repositories/jcenter

    FAILURE Build completed with 4 failures 1 Task failed with an exception What went wrong Execution failed for task 39 app
  • 用PyQt5写了个音乐播放器

    首先先展示一下界面 xff08 不美观但好用 xff09 除了不能看歌词功能该有的都有 xff0c 作为本地播放器还挺好用的 xff0c 界面是用PyQt5做的 下面是源代码 xff1a span class token keyword i
  • Consul+Ocelot搭建微服务实践--IdentityServer集成

    文章目录 1 IdentityServer介绍2 建立IdentityServer2 1 安装IdentityServer42 2 定义配置中心2 2 1 定义Client2 2 2 定义ApiResource2 2 3定义Identity