• 微信第三方登录


    最近业务需要,对接了微信,QQ,的第三方登录,下面以微信为例,总结下第三方登录的流程与使用到的技术

    一.用的核心的技术和规范:

      - SpringBoot 2.2.6.RELEASE

      - SpringCloud Nacos(由于整个项目是微服务项目,所以有用到其中的很多组件)

      - 第三方依赖 JustAuth  1.15.9 (这个轮子很好用,整合了市面上大多数的第三方认证授权)链接: https://github.com/justauth/JustAuth?utm_source=gold_browser_extension

          - Oauth2.0认证标准规范

    Oauth2.0认证流程(以微信 网站应用 为例),简单介绍一下Oauth2.0流程

          - 文档地址: https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

          - 微信Oauth2.0认证时序图:

      

       从时序图中可以看到第4步用户扫码确认后,第5步是微信开放平台回调到网站应用,回调域名配置在微信开放平台 授权回调域,表示用户扫码后只能回调到当前配置的域名下面

       

      

            

    二.后端代码

      1.获取微信二维码链接的接口:

    package com.leigod.center.user.nnpc.config;
    
    import lombok.Data;
    import me.zhyd.oauth.config.AuthConfig;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;
    
    /**
     * 第三方平台AppId ,AppSecret配置类
     * @author Sam.yang
     * @since 2021/1/29 17:38
     */
    @Data
    @Component
    @ConfigurationProperties(prefix = "oauth2")
    public class OAuthProperties {
    
        /**
         * QQ 配置
         */
        private AuthConfig qq;
    
        /**
         * github 配置
         */
        private AuthConfig github;
    
        /**
         * 微信 配置
         */
        private AuthConfig wechatOpen;
    
        /**
         * Google 配置
         */
        private AuthConfig google;
    
        /**
         * Microsoft 配置
         */
        private AuthConfig microsoft;
    
        /**
         * Mi 配置
         */
        private AuthConfig mi;
    }
    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //
    
    package me.zhyd.oauth.config;
    
    import com.xkcoding.http.config.HttpConfig;
    import java.util.List;
    /**
     * 配置类JustAuth 自带的
     */
    public class AuthConfig {
        private String clientId;
        private String clientSecret;
        private String redirectUri;
        private String alipayPublicKey;
        private boolean unionId;
        private String stackOverflowKey;
        private String agentId;
        private String codingGroupName;
        private HttpConfig httpConfig;
        private boolean ignoreCheckState;
        private List<String> scopes;
        private String deviceId;
        private Integer clientOsType;
        private String packId;
    
        public static AuthConfig.AuthConfigBuilder builder() {
            return new AuthConfig.AuthConfigBuilder();
        }
    
        public String getClientId() {
            return this.clientId;
        }
    
        public String getClientSecret() {
            return this.clientSecret;
        }
    
        public String getRedirectUri() {
            return this.redirectUri;
        }
    
        public String getAlipayPublicKey() {
            return this.alipayPublicKey;
        }
    
        public boolean isUnionId() {
            return this.unionId;
        }
    
        public String getStackOverflowKey() {
            return this.stackOverflowKey;
        }
    
        public String getAgentId() {
            return this.agentId;
        }
    
        public String getCodingGroupName() {
            return this.codingGroupName;
        }
    
        public HttpConfig getHttpConfig() {
            return this.httpConfig;
        }
    
        public boolean isIgnoreCheckState() {
            return this.ignoreCheckState;
        }
    
        public List<String> getScopes() {
            return this.scopes;
        }
    
        public String getDeviceId() {
            return this.deviceId;
        }
    
        public Integer getClientOsType() {
            return this.clientOsType;
        }
    
        public String getPackId() {
            return this.packId;
        }
    
        public void setClientId(String clientId) {
            this.clientId = clientId;
        }
    
        public void setClientSecret(String clientSecret) {
            this.clientSecret = clientSecret;
        }
    
        public void setRedirectUri(String redirectUri) {
            this.redirectUri = redirectUri;
        }
    
        public void setAlipayPublicKey(String alipayPublicKey) {
            this.alipayPublicKey = alipayPublicKey;
        }
    
        public void setUnionId(boolean unionId) {
            this.unionId = unionId;
        }
    
        public void setStackOverflowKey(String stackOverflowKey) {
            this.stackOverflowKey = stackOverflowKey;
        }
    
        public void setAgentId(String agentId) {
            this.agentId = agentId;
        }
    
        public void setCodingGroupName(String codingGroupName) {
            this.codingGroupName = codingGroupName;
        }
    
        public void setHttpConfig(HttpConfig httpConfig) {
            this.httpConfig = httpConfig;
        }
    
        public void setIgnoreCheckState(boolean ignoreCheckState) {
            this.ignoreCheckState = ignoreCheckState;
        }
    
        public void setScopes(List<String> scopes) {
            this.scopes = scopes;
        }
    
        public void setDeviceId(String deviceId) {
            this.deviceId = deviceId;
        }
    
        public void setClientOsType(Integer clientOsType) {
            this.clientOsType = clientOsType;
        }
    
        public void setPackId(String packId) {
            this.packId = packId;
        }
    
        public AuthConfig() {
        }
    
        public AuthConfig(String clientId, String clientSecret, String redirectUri, String alipayPublicKey, boolean unionId, String stackOverflowKey, String agentId, String codingGroupName, HttpConfig httpConfig, boolean ignoreCheckState, List<String> scopes, String deviceId, Integer clientOsType, String packId) {
            this.clientId = clientId;
            this.clientSecret = clientSecret;
            this.redirectUri = redirectUri;
            this.alipayPublicKey = alipayPublicKey;
            this.unionId = unionId;
            this.stackOverflowKey = stackOverflowKey;
            this.agentId = agentId;
            this.codingGroupName = codingGroupName;
            this.httpConfig = httpConfig;
            this.ignoreCheckState = ignoreCheckState;
            this.scopes = scopes;
            this.deviceId = deviceId;
            this.clientOsType = clientOsType;
            this.packId = packId;
        }
    
        public static class AuthConfigBuilder {
            private String clientId;
            private String clientSecret;
            private String redirectUri;
            private String alipayPublicKey;
            private boolean unionId;
            private String stackOverflowKey;
            private String agentId;
            private String codingGroupName;
            private HttpConfig httpConfig;
            private boolean ignoreCheckState;
            private List<String> scopes;
            private String deviceId;
            private Integer clientOsType;
            private String packId;
    
            AuthConfigBuilder() {
            }
    
            public AuthConfig.AuthConfigBuilder clientId(String clientId) {
                this.clientId = clientId;
                return this;
            }
    
            public AuthConfig.AuthConfigBuilder clientSecret(String clientSecret) {
                this.clientSecret = clientSecret;
                return this;
            }
    
            public AuthConfig.AuthConfigBuilder redirectUri(String redirectUri) {
                this.redirectUri = redirectUri;
                return this;
            }
    
            public AuthConfig.AuthConfigBuilder alipayPublicKey(String alipayPublicKey) {
                this.alipayPublicKey = alipayPublicKey;
                return this;
            }
    
            public AuthConfig.AuthConfigBuilder unionId(boolean unionId) {
                this.unionId = unionId;
                return this;
            }
    
            public AuthConfig.AuthConfigBuilder stackOverflowKey(String stackOverflowKey) {
                this.stackOverflowKey = stackOverflowKey;
                return this;
            }
    
            public AuthConfig.AuthConfigBuilder agentId(String agentId) {
                this.agentId = agentId;
                return this;
            }
    
            public AuthConfig.AuthConfigBuilder codingGroupName(String codingGroupName) {
                this.codingGroupName = codingGroupName;
                return this;
            }
    
            public AuthConfig.AuthConfigBuilder httpConfig(HttpConfig httpConfig) {
                this.httpConfig = httpConfig;
                return this;
            }
    
            public AuthConfig.AuthConfigBuilder ignoreCheckState(boolean ignoreCheckState) {
                this.ignoreCheckState = ignoreCheckState;
                return this;
            }
    
            public AuthConfig.AuthConfigBuilder scopes(List<String> scopes) {
                this.scopes = scopes;
                return this;
            }
    
            public AuthConfig.AuthConfigBuilder deviceId(String deviceId) {
                this.deviceId = deviceId;
                return this;
            }
    
            public AuthConfig.AuthConfigBuilder clientOsType(Integer clientOsType) {
                this.clientOsType = clientOsType;
                return this;
            }
    
            public AuthConfig.AuthConfigBuilder packId(String packId) {
                this.packId = packId;
                return this;
            }
    
            public AuthConfig build() {
                return new AuthConfig(this.clientId, this.clientSecret, this.redirectUri, this.alipayPublicKey, this.unionId, this.stackOverflowKey, this.agentId, this.codingGroupName, this.httpConfig, this.ignoreCheckState, this.scopes, this.deviceId, this.clientOsType, this.packId);
            }
    
            public String toString() {
                return "AuthConfig.AuthConfigBuilder(clientId=" + this.clientId + ", clientSecret=" + this.clientSecret + ", redirectUri=" + this.redirectUri + ", alipayPublicKey=" + this.alipayPublicKey + ", unionId=" + this.unionId + ", stackOverflowKey=" + this.stackOverflowKey + ", agentId=" + this.agentId + ", codingGroupName=" + this.codingGroupName + ", httpConfig=" + this.httpConfig + ", ignoreCheckState=" + this.ignoreCheckState + ", scopes=" + this.scopes + ", deviceId=" + this.deviceId + ", clientOsType=" + this.clientOsType + ", packId=" + this.packId + ")";
            }
        }
    }
    /**
     * 网页应用第三方登录
     *
     * @author Sam.yang
     * @since 2021/1/29 16:28
     */
    @Slf4j
    @RestController
    @RequestMapping(value = "/api/oauth")
    public class ApiAuthOpenController {
    
    
        @Autowired
        private OAuthProperties properties;
    
    
        /**
         * 重定向到微信
         *
         * @param oauthType 认证类型
         * @throws IOException
         */
        @PostMapping("/render/{oauthType}")
        @ApiOperation(value = "第三方账号登录")
        public BaseOutput<String> renderAuth(@PathVariable("oauthType") String oauthType) throws IOException {
    
            AuthRequest authRequest = this.getAuthRequest(oauthType);
            String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
            log.info("第三方登录 url:[{}]", authorizeUrl);
    
            return BaseOutput.success(authorizeUrl);
        }
        
    
        /**
         * 构建请求对象
         *
         * @param oauthType 第三方登录类型
         * @return {@link AuthRequest}
         */
        private AuthRequest getAuthRequest(String oauthType) {
            AuthDefaultSource authSource = AuthDefaultSource.valueOf(oauthType.toUpperCase());
            switch (authSource) {
                case QQ:
                    return this.getQqAuthRequest();
                case WECHAT_OPEN:
                    return this.getWechatAuthRequest();
                default:
                    throw new RuntimeException("暂不支持的第三方登录");
            }
        }
    
        /**
         * 构建QQ 认证请求对象
         *
         * @return {@link AuthRequest}
         */
        private AuthRequest getQqAuthRequest() {
    
            AuthConfig authConfig = properties.getQq();
            return new AuthQqRequest(authConfig);
        }
    
        /**
         * 构建微信 认证请求对象
         *
         * @return {@link AuthRequest}
         */
        private AuthRequest getWechatAuthRequest() {
            AuthConfig authConfig = properties.getWechatOpen();
            return new AuthWeChatOpenRequest(authConfig);
        }
    }
     /**
         * 获取第三方UnionID
         *
         * @param userOpen {@link UserOpen}
         * @return UnionID
         */
        private UserOpen getUnionID(UserOpen userOpen) {
            AuthCallback callback = AuthCallback.builder().code(userOpen.getCode()).state(userOpen.getState())
                    .build();
    
            AuthRequest authRequest = this.getAuthRequest(AuthEnum.valueOf(userOpen.getOpenType().toUpperCase())
                    .getDesc().toUpperCase());
    
            log.info("第三方登录请求参数:[{}]", JSON.toJSONString(authRequest));
            AuthResponse response = authRequest.login(callback);
            if (!response.ok()) {
                log.info("获取用户信息失败 response:[{}]", JSON.toJSONString(response));
                throw new BaseException(RetCode.ERROR);
            }
            log.info("第三方登录结果:[[}]", JSON.toJSONString(response));
    
            AuthUser user = (AuthUser) response.getData();
            AuthToken token = user.getToken();
            userOpen.setUnionId(token.getUnionId());
            return userOpen;
        }
  • 相关阅读:
    64位机配置iis 运行asp.net 程序(转载)
    病狗问题
    如何配置sqlcachedependence
    操作应用程序池
    自定义事件
    以下事情没做好决不能给客户演示
    判断用户ip是否在指定的ip段内
    silverlight4学习中解决的问题
    日历JS代码
    自己写的代码生成器ltscode2.0
  • 原文地址:https://www.cnblogs.com/july-sunny/p/14363485.html
Copyright © 2020-2023  润新知