oauth2统一认证授权_authenticationsuccessevent oauth2.0 统一认证-程序员宅基地

技术标签: 笔记  

oauth2.0统一认证授权

1.认证与授权

​ 最近学习整理了下认证授权相关实现,下面是大概的一些理解与学习过程。在分布式系统中每个服务都需要认证,授权。如果每个服务都实现一套认证授权的逻辑就会显得冗余,考虑到分布式系统共享性的特点,我们可以独立一个授权服务出来,可以对内部系统或者第三方应用提供认证。

1.1统一认证授权:

​ 提供独立的认证服务,统一处理认证授权。不论是什么用户还是不同种类的客户端,例如小程序,APP,web,都采用一致的认证,权限,会话机制。同时保持开放性,可以接入第三方外部应用。

2.OAuth2.0协议

​ Oauth是一个开放标准协议,他允许用户授权第三方应用访问他们存储在服务提供者上的信息。不需要提供用户名密码等敏感信息,而只需要提供服务提供者允许且用户(客户端)需要的信息。

(1).授权码模式

​ 最常见的例子就是我们平时微信支付宝的第三方登录。用户在浏览器访问网站A.如果该网站接入了微信认证。那么他可以申请微信认证。微信发放授权码,令牌等一系列操作,然后网站A持有该令牌去获取微信用户的信息。

在这里插入图片描述
1、客户端请求第三方授权用户进入网站A的登录页面,点击微信的图标以微信账号登录系统,点击“微信”出现一个二维码,此时用户扫描二维码,开始给网站A授权。

2、用户同意给客户端授权资源拥有者扫描二维码表示资源拥有者同意给客户端授权,微信会对资源拥有者的身份进行验证, 验证通过后,微信会询问用户是否给授权网站A访问自己的微信数据,用户点击“确认登录”表示同意授权,微信认证服务器会颁发一个授权码,并重定向到网站A.

3、客户端获取到授权码,请求认证服务器申请令牌此过程用户看不到,客户端应用程序请求认证服务器,请求携带授权码。

4、认证服务器向客户端响应令牌微信认证服务器验证了客户端请求的授权码,如果合法则给客户端颁发令牌,令牌是客户端访问资源的通行证。此交互过程用户看不到,当客户端拿到令牌后,用户在网站A看到已经登录成功。

5、客户端请求资源服务器的资源客户端携带令牌访问资源服务器的资源。网站A携带令牌请求访问微信服务器获取用户的基本信息。

6、资源服务器返回受保护资源,资源服务器校验令牌的合法性,如果合法则向用户响应资源信息内容。

以上流程只是oauth2.0的一种模式,即授权码模式。也是最oauth2中最安全的一种模式。授权码模式是oauth2中最安全的一种模式。观察上面的流程可以发现token始终没有经过浏览器也没有暴露密码,一切授权操作都是交给客户端的后台进行。因此这种模式对于第三方应用接入应用适用。

(2)密码模式:

在这里插入图片描述
流程:
1.用户想访问客户端,直接提供用户名密码给客户端。
2.客户端将用户名,密码交给授权服务直接获取令牌。
密码模式相对于授权码模式简单一些,但没有授权码模式那么安全,因为他讲用户名密码暴露给了客户端。这种模式一般只适用于客户端是我们内部开发的情况,对于接入外部应用就不行了。

3.Spring Cloud Security OAuth2

​ spring-Security-Oauth2是springcloud对oauth2的实现,oauth2的服务提供了两个服务。授权服务(Authorization Server)与资源服务(Resource server)

3.1授权服务

​ 授权服务(UAA) (Authorization Server)应包含对接入端以及登入用户的合法性进行验证并颁发token等功能。

AuthorizationEndpoint 服务于认证请求。默认 URL: /oauth/authorize 。
TokenEndpoint 服务于访问令牌的请求。默认 URL: /oauth/token 。

3.1.1授权服务搭建

​ 在父工程下建立security-uaa授权服务。
在这里插入图片描述
创建授权服务配置类: 用@EnableAuthorizationServer注解并且实现AuthorizationServerConfigurerAdapte配置授权服务。

@Configuration
@EnableAuthorizationServer
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {
    
}

AuthorizationServerConfigurerAdapter要求配置以下几个类:这几个对象由spring-oauth2进行管理,他们会被spring传入AuthorizationServerConfigurer中进行配置。

public class AuthorizationServerConfigurerAdapter implements AuthorizationServerConfigurer {
    
    public AuthorizationServerConfigurerAdapter() {
    
    }

    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    
    }

    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    
    }

    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    
    }
}

ClientDetailsServiceConfigurer:用来配置客户端详情服务,客户端的详细信息都在这里进行配置。客户端的信息在这里可以被写死,也可以将他们保存在数据库中。简单的来说这里就是来配置允许认证的客户端。

**AuthorizationServerEndpointsConfigurer:**用来配置令牌访问端点与令牌服务,申请令牌的url。令牌发放生成规则。

AuthorizationServerSecurityConfigurer:令牌的安全约束,访问令牌的安全约束。

3.1.2配置客户端详细信息

ClientDetailsServiceConfigurer可以将客户端详细信息配置在数据库,也可以配置在内存中(clientDetailsService),

clientDetailsService:clientDetailsService负责查找clientDetails

clientDetails:clientDetails中包括以下几个属性。

​ clientId:(必须的)用来标识客户的Id。

​ secret:(需要值得信任的客户端)客户端安全码,如果有的话。

​ scope:用来限制客户端的访问范围,如果为空(默认)的话,那么客户端拥有全部的访问范围。

​ authorizedGrantTypes:此客户端可以使用的授权类型,默认为空。

​ authorities:此客户端可以使用的权限

使用内存方式存储userDetails:

    @Override
    public void configure(ClientDetailsServiceConfigurer clients)
            throws Exception {
    
        //clients.withClientDetails(clientDetailsService); //存储在数据库中
        clients.inMemory()// 存储在内存中
                .withClient("c1")// client_id,客户端id,
                .secret(new BCryptPasswordEncoder().encode("secret"))//客户端密钥
                .resourceIds("res1","res2")//资源列表这里是一个列表可以配置多个
                .authorizedGrantTypes("authorization_code", "password","client_credentials","implicit","refresh_token")// 该client允许的授权类型authorization_code,password,refresh_token,implicit,client_credentials
                .scopes("all")// 允许的授权范围
                .autoApprove(false)//false跳转到授权页面
                //加上验证回调地址
                .redirectUris("http://www.baidu.com"); //并且返回授权码
    }

客户端的信息可以采用存储在数据库中的形式:
在这里插入图片描述

    @Autowired
    PasswordEncoder passwordEncoder;

    //将客户端信息存储到数据库
    @Bean
    public ClientDetailsService clientDetailsService(DataSource dataSource) {
    
        ClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource);
        ((JdbcClientDetailsService) clientDetailsService).setPasswordEncoder(passwordEncoder);
        return clientDetailsService;
    }
    public void configure(ClientDetailsServiceConfigurer clients)
            throws Exception {
    
        clients.withClientDetails(clientDetailsService);}
3.1.3配置令牌管理与访问端点

​ (1).配置令牌管理

​ 配置令牌存储单独写一个配置类进行配置,注入到spring容器中。

@Configuration
public class TokenConfig {
    

    //采用对称加密的方式生成令牌,统一在网关层进行校验
    private String SIGNING_KEY = "uaa123";

    @Bean
    public TokenStore tokenStore() {
    
        //JWT令牌存储方案
        return new JwtTokenStore(accessTokenConverter());
    }

    //配置令牌生成器
    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
    
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(SIGNING_KEY); //对称秘钥,资源服务器使用该秘钥来验证
        return converter;
    }
}

(2).定义AuthorizationServerTokenServices

​ 该接口实现了一些对令牌的管理。可以用它来修改令牌的格式与存储方式。

	//引入配置的授权令牌存储策略
	@Autowired
    private TokenStore tokenStore;

    @Autowired
    private ClientDetailsService clientDetailsService;
//令牌管理服务
    @Bean
    public AuthorizationServerTokenServices tokenService() {
    
        DefaultTokenServices service=new DefaultTokenServices();
        service.setClientDetailsService(clientDetailsService);//客户端详情服务
        service.setSupportRefreshToken(true);//支持刷新令牌
        service.setTokenStore(tokenStore);//令牌存储策略
        service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时
        service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天
        return service;
    }

配置授权码服务:AuthorizationServerEndpointsConfigurer 这个对象的实例可以完成令牌服务以及令牌endpoint配置。可以通过设置如下属性来决定支持的授权类型。

authenticationManager:认证管理器,当你选择了资源所有者密码(password)授权类型的时候,请设置这个属性注入一个 AuthenticationManager 对象。

authorizationCodeServices:这个属性是用来设置授权码服务的(即 AuthorizationCodeServices 的实例对象),主要用于 “authorization_code” 授权码类型模式。

@Bean
public AuthorizationCodeServices authorizationCodeServices(DataSource dataSource) {
    
    return new JdbcAuthorizationCodeServices(dataSource);//设置授权码模式的授权码如何存取
}

这里我们使用授权码模式,必须设置authorizationCodeServices

	@Autowired
    private AuthorizationCodeServices authorizationCodeServices; 
    @Autowired
    private AuthenticationManager authenticationManager;
@Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
    
        endpoints
                .authenticationManager(authenticationManager)//认证管理器
                .authorizationCodeServices(authorizationCodeServices)//授权码服务
                .tokenServices(tokenService())//令牌管理服务
                .allowedTokenEndpointRequestMethods(HttpMethod.POST);
    }
3.1.4配置令牌访问约束

AuthorizationServerSecurityConfigurer:用来配置令牌端点的安全约束

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security){
    
                security
                 //oauth/token_key是公开
                .tokenKeyAccess("permitAll()")                    
                 //oauth/check_token公开,开启token检查:资源服务拿到令牌可以请求oauth/check_token进行验证,如果采用jwt令牌的方式这里可以不用开启
                .checkTokenAccess("permitAll()") 
                    //表单认证(申请令牌)
                .allowFormAuthenticationForClients();				
    }

1.tokenkey这个endpoint当使用JwtToken且使用非对称加密时,资源服务用于获取公钥而开放的,这里指这个
endpoint完全公开。
2.checkToken这个endpoint完全公开
3.允许表单认证

3.2资源服务配置

新建一个服务
在这里插入图片描述

创建资源服务配置类

@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResouceServerConfig extends
ResourceServerConfigurerAdapter {
    
    //资源的标识,这里与授权服务中clientDetailsService中配置的resourceIds("res1","res2")相对应
	public static final String RESOURCE_ID = "res1";
    
    //这里配置资源服务
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
    
    resources.resourceId(RESOURCE_ID)
    .tokenServices(tokenService())
    .stateless(true);
}
   //这里的配置类似于HttpSecurity访问权限等一系列配置
@Override
public void configure(HttpSecurity http) throws Exception {
    
    http
    .authorizeRequests()
        //这里配置授权服务中允许访问的范围。
    .antMatchers("/**").access("#oauth2.hasScope('all')")
    .and().csrf().disable()
    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}

4.统一认证授权

在这里插入图片描述
流程:
接入方经过网关请求授权服务授权,授权服务验证,并返回token给接入应用
接入方携带token访问资源。
在网关层,会校验该接入方的访问权限,并且解析token为明文,将该token下发给对应资源服务
在资源服务拿到token后,还会继续根据token中的身份信息来校验是否有权限访问对应资源。

4.1搭建注册中心

所有微服务的请求都经过网关,网关从注册中心读取微服务的地址,将请求转发至微服务。
在这里插入图片描述

配置application.yml

spring:
  application:
    name: security_discovery
server:
  port: 53000 #启动端口
eureka:
  server:
    enable-self-preservation: false    #关闭服务器自我保护,客户端心跳检测15分钟内错误达到80%服务会保护,导致别人还认为是好用的服务
  client:
    register-with-eureka: false  #false:不作为一个客户端注册到注册中心
    instance-info-replication-interval-seconds: 10
    serviceUrl:
      defaultZone: http://localhost:${
    server.port}/eureka/

4.2搭建网关

​ 认证服务器生成jwt令牌,所有请求都会通过网关层校验。在网关层拦截请求获取令牌解析,并转发给对应的服务。这样各资源服务就不需要关注令牌解析了。网关就从当了上文中资源服务器的角色。

在这里插入图片描述

网关采用zuul,统一认证服务与资源服务都是网关下微服务,需要在网关上新增路由配置

zuul.routes.uaa‐service.stripPrefix = false
zuul.routes.uaa‐service.path = /uaa/**
zuul.routes.user‐service.stripPrefix = false
zuul.routes.user‐service.path = /source/**
4.2.1网关转发token

1.从请求中获取令牌内容。

2.组装明文token,转发给微服务,放入请求头中

public class AuthFilter extends ZuulFilter {
    

    @Override
    public String filterType() {
    
        return "pre";
    }

    @Override
    public int filterOrder() {
    
        return 0;
    }

    @Override
    public boolean shouldFilter() {
    
        return true;
    }

    @Override
    public Object run() throws ZuulException {
    
        RequestContext currentContext = RequestContext.getCurrentContext();
        //从Security上下文中拿到用户身份对象
        SecurityContext authentication = SecurityContextHolder.getContext();
        //判断其是否是oauth授予的身份信息
        if(!(authentication instanceof OAuth2Authentication)){
    
            return null;
        }

        OAuth2Authentication oAuth2Authentication =(OAuth2Authentication) authentication;

        Authentication userAuthentication = oAuth2Authentication.getUserAuthentication();

//        取出用户身份信息
        String principal = userAuthentication.getName();

//        取出用户权限
        List<String> authorities =  new ArrayList<>();

        Collection<? extends GrantedAuthority> authorities1 = userAuthentication.getAuthorities();

        for(GrantedAuthority authentication1:authorities1 ) {
    
            authorities.add(authentication1.getAuthority());
        }

        OAuth2Request oAuth2Request = oAuth2Authentication.getOAuth2Request();
        Map<String, String> requestParameters = oAuth2Request.getRequestParameters();
        Map<String,Object> jsonToken = new HashMap<>(requestParameters);

        if(userAuthentication != null) {
    
            jsonToken.put("principal" ,principal);
            jsonToken.put("authorities",authorities);
        }
//        把用户身份信息和授权信息放在json中,加入http的header中,转发给微服务
        //对其进行base64编码
        currentContext.addZuulRequestHeader("json-token",EncryptUtil.encodeUTF8StringBase64(JSON.toJSONString(jsonToken)));
        return null;
    }
}

配置令牌配置类:

在授权服务中我配置了采用对称加密方式生成令牌的配置类,这里直接拷贝到网关服务。

public class TokenConfig {
    

    private String SIGNING_KEY = "uaa123";

    @Bean
    public TokenStore tokenStore() {
    
        //JWT令牌存储方案
        return new JwtTokenStore(accessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
    
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(SIGNING_KEY); //对称秘钥,资源服务器使用该秘钥来验证
        return converter;
    }
4.2.2配置资源服务

主要配置的内容就是定义一些匹配规则,描述某个接入客户端需要什么样的权限才能访问某个微服务

@Configuration
public class ResouceServerConfig  {
    

    //资源的标识,这里与授权服务中clientDetailsService中配置的resourceIds("res1","res2")相对应
    public static final String RESOURCE_ID = "res1";

    //这里是对授权服务请求进行处理
    @Configuration
    @EnableResourceServer
    public class UAAServerConfig extends ResourceServerConfigurerAdapter {
    
        @Autowired
        private TokenStore tokenStore;

        @Override
        public void configure(ResourceServerSecurityConfigurer resources){
    
            resources.tokenStore(tokenStore).resourceId(RESOURCE_ID)
                    .stateless(true);
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {
    
            //这里配置只要是授权服务的请求都不进行拦截
            http.authorizeRequests()
                 .antMatchers("/uaa/**").permitAll();
        }
    }

    //这里是对3.2中的资源服务的请求进行处理
    @Configuration
    @EnableResourceServer
    public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    
        @Autowired
        private TokenStore tokenStore;

        @Override
        public void configure(ResourceServerSecurityConfigurer resources){
    
            //这里对令牌进行解析
            resources.tokenStore(tokenStore).resourceId(RESOURCE_ID)
                    .stateless(true);
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {
    
            http
                    .authorizeRequests()
                	//这里配置授权服务中允许访问的范围。
                    .antMatchers("/resource/**").access("#oauth2.hasScope('ROLE_API')");
        }
    }
    //配置其它的资源服务..
}
4.4.3用户权限拦截

在下游微服务拿到token后,应该怎么实现权限拦截?自己解析明文token,自己实现一套访问策略?在这里还是可以使用spring security来认证token,在资源服务中新建filter,用于从请求中获取token并解析,拿到用户身份信息与权限,将其放入springsecurity上下文中。

@Component
public class TokenAuthenticationFilter extends OncePerRequestFilter {
    


    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
    
            //解析出头中的token
        String token = httpServletRequest.getHeader("json-token");
        if(token!=null){
    
            String json = EncryptUtil.decodeUTF8StringBase64(token);
            //将token转成json对象
            JSONObject jsonObject = JSON.parseObject(json);
            //用户身份信息
            UserDTO userDTO = JSON.parseObject(jsonObject.getString("principal"), UserDTO.class);
            //用户权限
            JSONArray authoritiesArray = jsonObject.getJSONArray("authorities");
            String[] authorities = authoritiesArray.toArray(new String[authoritiesArray.size()]);
            //将用户信息和权限填充 到用户身份token对象中
            UsernamePasswordAuthenticationToken authenticationToken
                    = new UsernamePasswordAuthenticationToken(userDTO,null, AuthorityUtils.createAuthorityList(authorities));
            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
            //将authenticationToken填充到安全上下文
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            
        }
        filterChain.doFilter(httpServletRequest,httpServletResponse);

    }
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_39271545/article/details/118197556

智能推荐

机器学习模型评分总结(sklearn)_model.score-程序员宅基地

文章浏览阅读1.5w次,点赞10次,收藏129次。文章目录目录模型评估评价指标1.分类评价指标acc、recall、F1、混淆矩阵、分类综合报告1.准确率方式一:accuracy_score方式二:metrics2.召回率3.F1分数4.混淆矩阵5.分类报告6.kappa scoreROC1.ROC计算2.ROC曲线3.具体实例2.回归评价指标3.聚类评价指标1.Adjusted Rand index 调整兰德系数2.Mutual Informa..._model.score

Apache虚拟主机配置mod_jk_apache mod_jk 虚拟-程序员宅基地

文章浏览阅读344次。因工作需要,在Apache上使用,重新学习配置mod_jk1. 分别安装Apache和Tomcat:2. 编辑httpd-vhosts.conf: LoadModule jk_module modules/mod_jk.so #加载mod_jk模块 JkWorkersFile conf/workers.properties #添加worker信息 JkLogFil_apache mod_jk 虚拟

Android ConstraintLayout2.0 过度动画MotionLayout MotionScene3_android onoffsetchanged-程序员宅基地

文章浏览阅读335次。待老夫kotlin大成,扩展:MotionLayout 与 CoordinatorLayout,DrawerLayout,ViewPager 的 交互众所周知,MotionLayout 的 动画是有完成度的 即Progress ,他在0-1之间变化,一.CoordinatorLayout 与AppBarLayout 交互时,其实就是监听 offsetliner 这个 偏移量的变化 同样..._android onoffsetchanged

【转】多核处理器的工作原理及优缺点_多核处理器怎么工作-程序员宅基地

文章浏览阅读8.3k次,点赞3次,收藏19次。【转】多核处理器的工作原理及优缺点《处理器关于多核概念与区别 多核处理器工作原理及优缺点》原文传送门  摘要:目前关于处理器的单核、双核和多核已经得到了普遍的运用,今天我们主要说说关于多核处理器的一些相关概念,它的工作与那里以及优缺点而展开的分析。1、多核处理器  多核处理器是指在一枚处理器中集成两个或多个完整的计算引擎(内核),此时处理器能支持系统总线上的多个处理器,由总..._多核处理器怎么工作

个人小结---eclipse/myeclipse配置lombok_eclispe每次运行个新项目都需要重新配置lombok吗-程序员宅基地

文章浏览阅读306次。1. eclipse配置lombok 拷贝lombok.jar到eclipse.ini同级文件夹下,编辑eclipse.ini文件,添加: -javaagent:lombok.jar2. myeclipse配置lombok myeclipse像eclipse配置后,定义对象后,直接访问方法,可能会出现飘红的报错。 如果出现报错,可按照以下方式解决。 ..._eclispe每次运行个新项目都需要重新配置lombok吗

【最新实用版】Python批量将pdf文本提取并存储到txt文件中_python批量读取文字并批量保存-程序员宅基地

文章浏览阅读1.2w次,点赞31次,收藏126次。#注意:笔者在2021/11/11当天调试过这个代码是可用的,由于pdfminer版本的更新,网络上大多数的语法没有更新,我也是找了好久的文章才修正了我的代码,仅供学习参考。1、把pdf文件移动到本代码文件的同一个目录下,笔者是在pycharm里面运行的项目,下图中的x1文件夹存储了我需要转换成文本文件的所有pdf文件。然后要在此目录下创建一个存放转换后的txt文件的文件夹,如图中的txt文件夹。2、编写代码 (1)导入所需库# coding:utf-8import ..._python批量读取文字并批量保存

随便推点

Scala:访问修饰符、运算符和循环_scala ===运算符-程序员宅基地

文章浏览阅读1.4k次。http://blog.csdn.net/pipisorry/article/details/52902234Scala 访问修饰符Scala 访问修饰符基本和Java的一样,分别有:private,protected,public。如果没有指定访问修饰符符,默认情况下,Scala对象的访问级别都是 public。Scala 中的 private 限定符,比 Java 更严格,在嵌套类情况下,外层_scala ===运算符

MySQL导出ER图为图片或PDF_数据库怎么导出er图-程序员宅基地

文章浏览阅读2.6k次,点赞7次,收藏19次。ER图导出为PDF或图片格式_数据库怎么导出er图

oracle触发器修改同一张表,oracle触发器中对同一张表进行更新再查询时,需加自制事务...-程序员宅基地

文章浏览阅读655次。CREATE OR REPLACE TRIGGER Trg_ReimFactBEFORE UPDATEON BP_OrderFOR EACH ROWDECLAREPRAGMA AUTONOMOUS_TRANSACTION;--自制事务fc varchar2(255);BEGINIF ( :NEW.orderstate = 2AND :NEW.TransState = 1 ) THENBEG..._oracle触发器更新同一张表

debounce与throttle区别及其应用场景_throttle和debounce应用在哪些场景-程序员宅基地

文章浏览阅读513次。目录概念debouncethrottle实现debouncethrottle应用场景debouncethrottle场景举例debouncethrottle概念debounce字面理解是“防抖”,何谓“防抖”,就是连续操作结束后再执行,以网页滚动为例,debounce要等到用户停止滚动后才执行,将连续多次执行合并为一次执行。throttle字面理解是“节流”,何谓“节流”,就是确保一段时..._throttle和debounce应用在哪些场景

java操作mongdb【超详细】_java 操作mongodb-程序员宅基地

文章浏览阅读526次。regex() $regex 正则表达式用于模式匹配,基本上是用于文档中的发现字符串 (下面有例子)注意:若未加 @Field("名称") ,则识别mongdb集合中的key名为实体类属性名。也可以对数组进行索引,如果被索引的列是数组时,MongoDB会索引这个数组中的每一个元素。也可以对整个Document进行索引,排序是预定义的按插入BSON数据的先后升序排列。save: 若新增数据的主键已经存在,则会对当前已经存在的数据进行修改操作。_java 操作mongodb

github push 推送代码失败. 使用ssh rsa key. remote: Support for password authentication was removed._git push remote: support for password authenticati-程序员宅基地

文章浏览阅读1k次。今天push代码到github仓库时出现这个报错TACKCHEN-MB0:tc-image tackchen$ git pushremote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.remote: Please see https://github.blog/2020-12-15-token-authentication_git push remote: support for password authentication was removed on august 1