基于JustAuth实现第三方登录

仅供参考.不具有通用性.

首先,依赖文件中添加


    1.13.2
    1.3.2

    me.zhyd.oauth
    JustAuth
    ${JustAuth.version}




    com.xkcoding.justauth
    justauth-spring-boot-starter
    ${justauth.version}




    org.springframework.boot
    spring-boot-starter-freemarker

    
        
            src/main/resources
            true
        
        
            src/main/java
            
                **/*.xml
                **/*.json
                **/*.ftl      用于查找templates中用于跳转的ftl文件
            
        
    

resources文件夹下新建templates目录,新建thirdLogin.ftl用于做页面跳转.window.opener.postMessage("${token}", "*");与前端window.addEventListener('message', receiveMessage, false)对应.



    
    
    
    第三方登录


登陆中...


新建application-just.yml 用来单独存放justauth的配置信息

# 第三方登录
justauth:
  enabled: true
  extend:
    enum-class: com.alvis.exam.justauth.AuthExtendSource
    config:
      VPGIT:
        requestClass: com.alvis.exam.justauth.AuthVpGitRequest
        client-id: gitlab上为此application配置生成id
        client-secret: gitlab上为此application配置生成的secret
        redirect-uri: gitlab上配置的返回地址,如http://localhost:8081/xxxxx/xxx/xxxx/thirdLogin/xxgit/callback
  cache:
    # 缓存类型(default-使用JustAuth内置的缓存、redis-使用Redis缓存、custom-自定义缓存)
    type: default
    prefix: 'JUSTAUTH::STATE::'
    # 超时时长
    timeout: 1h
修改application.yml配置
spring:
  profiles:
    active:  ${spring.profiles.active}
    include:
      - just
  #配置freemarker
  freemarker:
    # 设置模板后缀名
    suffix: .ftl
    # 设置文档类型
    content-type: text/html
    # 设置页面编码格式
    charset: UTF-8
    # 设置页面缓存
    cache: false
    prefer-file-system-access: false
    # 设置ftl文件路径
    template-loader-path:
      - classpath:/templates
    settings:
      classic_compatible: true

自定义第三方认证扩展

public enum AuthExtendSource implements AuthSource {
    xxGIT {
        @Override
        public String authorize() {
            return "公司私服域名/gitlab/oauth/authorize";
        }

        @Override
        public String accessToken() {
            return "公司私服域名/gitlab/oauth/token";
        }

        @Override
        public String userInfo() {
            return "公司私服域名/gitlab/api/v4/user";
        }
    }
}
public class AuthxxGitRequest extends AuthDefaultRequest {
    public AuthVpGitRequest(AuthConfig config) {
        super(config, AuthExtendSource.xxGIT);
    }

    public AuthVpGitRequest(AuthConfig config, AuthStateCache authStateCache) {
        super(config, AuthExtendSource.xxGIT, authStateCache);
    }

    @Override
    protected AuthToken getAccessToken(AuthCallback authCallback) {
        HttpResponse response = this.doPostAuthorizationCode(authCallback.getCode());
        JSONObject object = JSONObject.parseObject(response.body());
        this.checkResponse(object);
        return AuthToken.builder().accessToken(object.getString("access_token")).refreshToken(object.getString("refresh_token")).idToken(object.getString("id_token")).tokenType(object.getString("token_type")).scope(object.getString("scope")).build();
    }

    @Override
    protected AuthUser getUserInfo(AuthToken authToken) {
        HttpResponse response = this.doGetUserInfo(authToken);
        JSONObject object = JSONObject.parseObject(response.body());
        this.checkResponse(object);
        return AuthUser.builder().uuid(object.getString("id")).username(object.getString("username")).nickname(object.getString("name")).avatar(object.getString("avatar_url")).blog(object.getString("web_url")).company(object.getString("organization")).location(object.getString("location")).email(object.getString("email")).remark(object.getString("bio")).gender(AuthUserGender.UNKNOWN).token(authToken).source(this.source.toString()).build();
    }

    private void checkResponse(JSONObject object) {
        if (object.containsKey("error")) {
            throw new AuthException(object.getString("error_description"));
        } else if (object.containsKey("message")) {
            throw new AuthException(object.getString("message"));
        }
    }

    @Override
    public String authorize(String state) {
        return UrlBuilder.fromBaseUrl(super.authorize(state)).queryParam("scope", "read_user+openid+profile+email").build();
    }
    
}

controller层

@Controller
@RequestMapping("/thirdLogin")
@Slf4j
public class ThirdLoginController {
   @Autowired
   private ISysUserService sysUserService;
   
   @Autowired
   private BaseCommonService baseCommonService;
   @Autowired
    private RedisUtil redisUtil;
   @Autowired
   private AuthRequestFactory factory;

   @RequestMapping("/render/{source}")
    public void render(@PathVariable("source") String source, HttpServletResponse response) throws IOException {
        log.info("第三方登录进入render:" + source);
        AuthRequest authRequest = factory.get(source);
        String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
        log.info("第三方登录认证地址:" + authorizeUrl);
        response.sendRedirect(authorizeUrl);
    }
   
   @RequestMapping("/{source}/callback")
    public String login(@PathVariable("source") String source, AuthCallback callback,ModelMap modelMap) {
      log.info("第三方登录进入callback:" + source + " params:" + JSONObject.toJSONString(callback));
        AuthRequest authRequest = factory.get(source);
        AuthResponse response = authRequest.login(callback);
        log.info(JSONObject.toJSONString(response));
        VpResult result = new VpResult();
        if(response.getCode()==2000) {
            
           JSONObject data = JSONObject.parseObject(JSONObject.toJSONString(response.getData()));
           String username = data.getString("username");
           String avatar = data.getString("avatar");
           String uuid = data.getString("uuid");
           
           //判断有没有这个人
           LambdaQueryWrapper query = new LambdaQueryWrapper();
           query.eq(SysUser::getThirdId, uuid);
           query.eq(SysUser::getThirdType, source);
           List thridList = sysUserService.list(query);
           SysUser user = null;
           if(thridList==null || thridList.size()==0) {
              user = new SysUser();
              user.setActivitiSync(CommonConstant.ACT_SYNC_0);
              user.setDelFlag(CommonConstant.DEL_FLAG_0);
              user.setStatus(1);
              user.setThirdId(uuid);
              user.setThirdType(source);
              user.setAvatar(avatar);
              user.setUsername(uuid);
              user.setRealname(username);
              
              //设置初始密码
              String salt = oConvertUtils.randomGen(8);
             user.setSalt(salt);
             String passwordEncode = PasswordUtil.encrypt(user.getUsername(), "123456", salt);
             user.setPassword(passwordEncode);
              sysUserService.saveThirdUser(user);
           }else {
              //已存在 只设置用户名 不设置头像
              user = thridList.get(0);
              //user.setUsername(username);
              //sysUserService.updateById(user);
           }
           // 生成token
          String token = JwtUtil.sign(user.getUsername(), user.getPassword());
          redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
          // 设置超时时间
          redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 1000);

         //update-begin-author:taoyan date:20200812 for:登录缓存用户信息
         LoginUser redisUser = new LoginUser();
         BeanUtils.copyProperties(user, redisUser);
         redisUser.setPassword(SecureUtil.md5(user.getPassword()));
         redisUtil.set(CacheConstant.SYS_USERS_CACHE_JWT +":" +token, redisUser);
         redisUtil.expire(CacheConstant.SYS_USERS_CACHE_JWT +":" +token, JwtUtil.EXPIRE_TIME*2 / 1000);
         //update-end-author:taoyan date:20200812 for:登录缓存用户信息

          modelMap.addAttribute("token", token);
      //update-begin--Author:wangshuai  Date:20200729 for:接口在签名校验失败时返回失败的标识码 issues#1441--------------------
        }else{
         modelMap.addAttribute("token", "登录失败");
      }
      //update-end--Author:wangshuai  Date:20200729 for:接口在签名校验失败时返回失败的标识码 issues#1441--------------------
        result.setSuccess(false);
        result.setMessage("第三方登录异常,请联系管理员");
        return "thirdLogin";
    }
   
   @SuppressWarnings("unchecked")
   @RequestMapping(value = "/getLoginUser/{token}", method = RequestMethod.GET)
   @ResponseBody
   public VpResult getLoginUser(@PathVariable("token") String token) throws Exception {
      VpResult result = new VpResult();
      String username = JwtUtil.getUsername(token);
      
      //1. 校验用户是否有效
      SysUser sysUser = sysUserService.getUserByName(username);
      result = sysUserService.checkUserIsEffective(sysUser);
      if(!result.isSuccess()) {
         return result;
      }
      JSONObject obj = new JSONObject();
      //用户登录信息
      obj.put("userInfo", sysUser);
      //token 信息
      obj.put("token", token);
      result.setDataInfo(obj);
      result.setSuccess(true);
      result.setReturnCode(200);
      baseCommonService.addLog("用户名: " + username + ",登录成功[第三方用户]!", CommonConstant.LOG_TYPE_1, null);
      return result;
   }
   
}

注意vue.config.js下的网关映射

基于JustAuth实现第三方登录_第1张图片

vue 

其他登陆方式

methods中

/**
   * 第三方登录
   * @param token
   * @returns {*}
   */
thirdLoginApi (token) {
  return axios({
    url: process.env.VUE_APP_API + `/thirdLogin/getLoginUser/${token}`,
    method: 'get',
    headers: {
      'Content-Type': 'application/json;charset=UTF-8'
    }
  })
},

ThirdLogin (token) {
  let that = this
  return new Promise((resolve, reject) => {
    console.log('token:', token)
    that.thirdLoginApi(token).then(response => {
      if (response.data.code === 1) {
        resolve(response)
        this.loginForm.password = response.userInfo.password
        console.log('success', response)
      } else {
        reject(response)
        console.log('failed')
      }
    }).catch(error => {
      reject(error)
    })
  }).catch((e) => {})
},

// 第三方登录
onThirdLogin (source) {
  let url = process.env.VUE_APP_API + `/thirdLogin/render/${source}`
  window.open(url, `login ${source}`, 'height=500, width=500, top=0, left=0, toolbar=no, menubar=no, scrollbars=no, resizable=no,location=n o, status=no')
  let that = this
  let receiveMessage = function (event) {
    var origin = event.origin
    console.log('origin', origin)

    let token = event.data
    console.log('event.data', token)
    that.ThirdLogin(token).then(result => {
      if (result && result.data.code === 1) {
        let _this = that
        this.loading = true
        _this.loginForm.userName = result.data.response.token
        console.log('username:', _this.loginForm.userName)
        _this.setUserName(_this.loginForm.userName)
        _this.loginForm.password = result.data.response.userInfo.password
        console.log('loginForm:', _this.loginForm)
        loginApi.login(_this.loginForm).then(function (result) {
          console.log('loginapi result', result)
          if (result && result.code === 1) {
            console.log('登陆成功')
            window.removeEventListener('message', receiveMessage, false)       // 解除监听
            _this.setUserName(_this.loginForm.userName)
            _this.$router.push({ path: '/' })
          } else {
            _this.loading = false
            _this.$message.error(result.message)
            window.removeEventListener('message', receiveMessage, false)
          }
        }).catch(function (reason) {
          _this.loading = false
        })
      } else {
        return false
      }
    })
  }
  window.addEventListener('message', receiveMessage, false)
},

你可能感兴趣的:(工作总结)