• 网站使用谷歌登录 oauth java nuxt auth


    前言

    • 最近做谷歌快捷登录,走了比较多弯路,这里做个记录,希望对后面的人有所帮助。

    代码使用技术

    后端

    • Spring Boot为主。

    前端

    • nuxt、vue为主,还使用了nuxt-auth模块。

    准备工作

    谷歌控制台

    文档

    前端

    npm install --save-exact @nuxtjs/auth-next
    npm install @nuxtjs/axios
    
    • 1
    • 2
    • 如果你是yarn
    yarn add --exact @nuxtjs/auth-next
    yarn add @nuxtjs/axios
    
    • 1
    • 2
    • nuxt.config.js配置。clientId就是前面申请的客户端id。
      // nuxt auth模块配置
      auth: {
        strategies: {
          google: {
          // 这个就是前面申请的客户端id
            clientId: 'xxxx.apps.googleusercontent.com',
            codeChallengeMethod: '',
            responseType: 'code',
            endpoints: {
            // /api是项目统一前缀,之前配置过统一代理所以不用加前缀
              token: '/api/google', // somm backend url to resolve your auth with google and give you the token back
              userInfo: '/api/auth/user' // the endpoint to get the user info after you recived the token 
            },
             token: {
              property: 'data',
              type: 'Bearer',
              maxAge: 1800
            },
            user: {
              property: 'data'
            },
          },
        },
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 登录页面login.vue
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    后端

    • 其实前面的步骤nuxt auth已经帮我们做了,后端只需要完成4和5就能拿到用户信息了。
      在这里插入图片描述
      在这里插入图片描述

    • controller层,restTemplateProxy是做了代理的。

        @Bean
        public RestTemplate restTemplateProxy() {
            RestTemplate restTemplate = new RestTemplate();
            SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory();
            simpleClientHttpRequestFactory.setProxy(new Proxy(Proxy.Type.HTTP,new InetSocketAddress("192.168.3.2",1080))); // 添加代理 ip 和 port 即可
            restTemplate.setRequestFactory(simpleClientHttpRequestFactory);
            return restTemplate;
        }
        
     
        @PostMapping("/google")
       public R google(GooglePayloadReq googlePayload) {
       	// token接口
       		//        设置请求头,请求类型为x-www-form-urlencoded
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
    //        设置请求参数
            MultiValueMap map = new LinkedMultiValueMap<>();
            map.add("code", googlePayload.getCode());
            // 客户id
            map.add("client_id", "4xxxxs.googleusercontent.com");
            // 客户密钥
            map.add("client_secret", "xxxx");
            map.add("redirect_uri", "http://localhost:81/login");
            // web 固定
            map.add("grant_type", "authorization_code");
            //用HttpEntity封装整个请求报文
            HttpEntity> request = new HttpEntity<>(map, headers);
            String responseBody = restTemplateProxy.postForObject("https://oauth2.googleapis.com/token", request, String.class);
            logger.info(" token responseBody [ {} ]", responseBody);
            Assert.isEmpty(responseBody, "第三方接口返回异常");
           GoogleTokenRes res = objectMapperFace.readValue(responseBody, GoogleTokenRes.class)
     		 //	 tokeninfo 接口
     		  tokenInfo(res)
     		  return R.ok("tokenxxxxx");
       }
       
        public GoogleTokenInfoRes tokenInfo(GoogleTokenRes googleTokenRes) {
           // 注意接口返回的是id_token字段,我用了@JsonProperty注解对应上的
            String responseBody = restTemplateProxy.getForObject(
                    "https://oauth2.googleapis.com/tokeninfo?id_token="+googleTokenRes.getIdToken(), String.class);
            logger.info("获取用户信息 res [ {} ]", responseBody);
            Assert.isEmpty(responseBody, "第三方接口返回异常,获取用户信息");
            return objectMapperFace.readValue(responseBody, GoogleTokenInfoRes.class);
        }
        
       @GetMapping("/auth/user")
        public R authUser(HttpServletRequest request) {
            logger.info("authUser");
            return R.ok(new Users());
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • ObjectMapperFace.java
     
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.works.common.exception.ServiceException;
    
    /**
     * @author Zhou Zhongqing
     * @ClassName ObjectMapperWarp
     * @description: 装饰ObjectMapper对象
     * @date 2022-08-10 17:50
     */
    public class ObjectMapperFace {
    
        private ObjectMapper objectMapper;
    
    
        public ObjectMapperFace(ObjectMapper objectMapper) {
            this.objectMapper = objectMapper;
        }
    
        public ObjectMapper getObjectMapper() {
            return objectMapper;
        }
    
        public void setObjectMapper(ObjectMapper objectMapper) {
            this.objectMapper = objectMapper;
        }
    
        /**
         * 对象转json
         * @param value
         * @return
         */
        public String writeValueAsString(Object value) {
            try {
               return objectMapper.writeValueAsString(value);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
                throw new ServiceException(e.getMessage());
            }
        }
    
        /**
         * json转对象
         * @param content
         * @param valueType
         * @return
         * @param 
         */
        public  T readValue(String content, Class valueType) {
            try {
                return objectMapper.readValue(content,valueType);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
                throw new ServiceException(e.getMessage());
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    运行效果

    在这里插入图片描述

    在这里插入图片描述

    小结

    • 拿到用户信息后,我们就用sub字段与我们业务系统进行绑定。判断我们数据库有没有这个用户。
  • 相关阅读:
    Kubernetes - Kubernetes详解;安装部署(一)
    centos7安装nodejs运行环境及卸载
    关于loss.backward()optimizer.step()optimizer.zero_grad()的顺序
    YGG 联合创始人 Gabby Dizon 在 Neckerverse 峰会上分享边玩边赚的故事
    MyCat搭建读写分离
    springboot+学校运动会信息管理 毕业设计-附源码231058
    c++20模块导入module
    MySQL数据同步&归档使用工具总结
    linux命令
    【FreeRTOS】FreeRTOS移植stm32详细步骤介绍
  • 原文地址:https://blog.csdn.net/baidu_19473529/article/details/126283186