Oauth2.0 protocol in Internet architecture

//  今天主要讲这么几个问题
1.如何保证api接口合理安全调用
2.oauth2.0授权认证平台设计原理
3.oauth2.0认证协议的四种模式
4.oauth2.0实现对api接口保护
https://www.cnblogs.com/blowing00/p/4521135.html
看大佬的讲解吧
我的api 如果让很多合作伙伴访问 请问怎么做
合作伙伴可能会调用到我的接口,此时怎么保证我的开放接口的安全性
我吧我的api 提供给合作伙伴公司,我该如何管理我这个开放接口

这些合作伙伴想要调用我接口,必须要求 申请一个appKey和这个secret  用appkey和密码换取access_token,有了这个access_token 才可以访问我接口
 
 oauth2.0授权协议
  // oauth2.0 有哪几种
  授权码>  获取access_token通过access_token你才能调用我接口
  密码>  你在调用我接口的时候传userName和password 
  简化模式
  客户端模式
  调用接口传递令牌(access_token) 为什么比较安全
  因为令牌是临时且唯一的,有时间限制的
   假设现在我们公司接口需要被很多合作伙伴调用的情况西
   首先我先搭建一个 认证管理web 平台
	就是说你要在我平台申请一个appid和appkey
	
  oauth2.0协议授权模式
  1.合作伙伴首先先要申请appid和appkey  区分不同的合作伙伴[appid 是终身不会发生变化,appkey是可以修改的]
 2.合作伙伴用这个appid和appkey申请一个授权code (认证授权获取授权码code),
 3.拿到code获取 accesstoken,再然后拿到这个access_token 才可以掉我接口 

Insert picture description here


Let's take a look at Zhihu's WeChat scan code login
Insert picture description here

https://open.weixin.qq.com/connect/qrconnect?
appid=wx268fcfe924dcb171
&redirect_uri=https%3A%2F%2Fwww.zhihu.com%2Foauth%2Fcallback%2Fwechat%3Faction%3Dlogin%26from%3D
&response_type=code
&scope=snsapi_login
&state=59346f327367534969737557456a5a556e315555325235576e425a5a384f4430#wechat
首先第一步 他会生成一个授权连接,获取授权码code
// 我们可以对比看看微信得官网
https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

Insert picture description here

嗯,是不是一样的,当我们点击同意的时候,回生成一个code 来回调我们的redirect_uri  
只不过这里页面跳转的太快 我就不演示了
第二步, 后台回用这个code 来生成一个access_token,  意思是我只要拿到这个accessToken就可以调用接口
第三步:根据这个accessToken	此时就可以调用微信接口了,可以获取用户的openId[此时这个openID是腾讯对qq账户设置一个开放的userId,而不是真实的userId]
第四步  根据用户的openId获取用户的信息
accesstoken 有效期 2小时 如果这个accesstoken 过期可以去使用refresh_token去获取最新的access_token
oauth2.0协议角色划分 

Insert picture description here

我们再来看这张图  oauth2.0角色的划分无非就是2个角色
 一个AuthenticationService【认证授权中心】 认证授权,根据appkey 获取授权码,accesstoken 
 一个ResourceService【资源管理器】 被开放的接口检查
 

然后我们先通过Springsecurity搭建一个AuthenticationService
package com.lvhao.auth.service.config;

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
// 配置登录账号密码
@Component
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    
    
    @Bean
    public PasswordEncoder passwordEncoder() {
    
    
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    
    
        http.authorizeRequests()
                .anyRequest().authenticated() // 所有请求都要通过认证
                .and()
                .httpBasic()
                .and()
                .csrf().disable();// 关闭跨域保护

    }

    // 配置登录账号密码
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    
    
        auth.inMemoryAuthentication()
                .withUser("mayiketi")
                .password(passwordEncoder().encode("123456"))
                .authorities("/*");
    }
}

package com.lvhao.auth.service.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.stereotype.Component;
//
@Component
@EnableAuthorizationServer// 当前项目是一个认证授权中心  开启认证授权
public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
    
    
    @Autowired
    PasswordEncoder passwordEncoder;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    
    
// 检查accesstoken权限
        //允许表单提交,检查accesstoken是否有效的情况下  必须加配置 权限放开
         security.allowFormAuthenticationForClients()
                .checkTokenAccess("permitAll()");
    }

    /*
     * 分配我的appid和appkey
     * */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    
    
        clients.inMemory()
                /*appid*/
                .withClient("mayikt_appid")
                /*密钥*/
                .secret(passwordEncoder.encode( "mayikt_pwd"))
                .authorizedGrantTypes("authorization_code")
                /*所有的接口都可以方位*/
                /*member-service表示只能访问到我的member服务接口不能访问别的接口*/
                //分配appid调用接口的权限
                .scopes("all")
                 .resourceIds("mayikt_resource")
                //  用户选择授权之后跳转到该地址传递code授权码
                .redirectUris("https://www.baidu.com/");
    }
}

Insert picture description here

Insert picture description here

我此时的回调地址配置的百度  当点击授权的时候 此时会跳到回调地址上返回一个code 

Insert picture description here

  然后第二步就是  用这个code 来换取access_token
  http://localhost:9000/oauth/token?code=2rX4gF&grant_type=authorization_code
  &redirect_uri=https://www.baidu.com/
  &scope=all
  &client_id=mayikt_appid
  &client_secret=mayikt_pwd

Insert picture description here

  看到了吧 根据此时这code 就可以拿到access_token

Insert picture description here

我们下一步可以检查这个token 是否有效  
http://localhost:9000/oauth/check_token?token=787cb830-71b6-4c4d-a7a8-861145efb075

------------------------------------------------?

嗯 我们的认证管理器就搭建完毕了, 然后我们现在搭建我们的资源管理器


@Configuration
@EnableResourceServer
public class ResourceConfig extends ResourceServerConfigurerAdapter {
    
    
    @Value("mayikt_appid")

    private String mayiktAppid;
    @Value("mayikt_pwd")
    private String mayiktAppSecret;

    @Bean
    public PasswordEncoder passwordEncoder() {
    
    
        return new BCryptPasswordEncoder();
    }
    //  去拦截请求判断有没有去传递accesstoken 同时检查accesstoken 是否有效
    @Primary
    @Bean
    public RemoteTokenServices remoteTokenServices() {
    
    

        final RemoteTokenServices tokenServices = new RemoteTokenServices();
        //设置授权服务器cache_token 的完整地址       http://localhost:9000/oauth/check_token
        tokenServices.setCheckTokenEndpointUrl("http://localhost:9000/oauth/check_token");
        //APPID
        tokenServices.setClientId(mayiktAppid);
        //KEY
        tokenServices.setClientSecret(mayiktAppSecret);
        return tokenServices;
     }

    @Override
    public void configure(HttpSecurity http) throws Exception {
    
    
        //设置创建session策略
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
       http.authorizeRequests().anyRequest().authenticated();

    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
    
    
        resources.resourceId("mayikt_resource").stateless(true);
    }
}

每当访问资源管理器的时候, 或者调用api的时候,资源管理器首先第一步操作就是调用这个check 来看此时的access_token 是否有效

Insert picture description here

我有个这么个接口,如果此时不携带access_token 的话就会报错异常 

Insert picture description here

看此时携带这个token 的话就不会有异常了 ,并且可以正常访问了

Insert picture description here
Insert picture description here

我们也可以用 jwt的形式 通过 Bearer+code 写在头中 
  嗯 最后一个问题 就是互联网架构中我们的接口安全如何去做

Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_43689953/article/details/109723203