parent
43df2b3f8b
commit
e03a71776a
19 changed files with 517 additions and 23 deletions
@ -0,0 +1,31 @@ |
||||
package com.kob.backend.controller.user.account.acwing; |
||||
|
||||
import com.alibaba.fastjson.JSONObject; |
||||
import com.kob.backend.service.user.account.acwing.AcappService; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.RequestParam; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
|
||||
import java.util.Map; |
||||
|
||||
@RestController |
||||
public class AcappController { |
||||
@Autowired |
||||
private AcappService acappService; |
||||
|
||||
@GetMapping("/api/user/account/acwing/acapp/apply_code/") |
||||
public JSONObject applyCode() { |
||||
return acappService.applyCode(); |
||||
} |
||||
|
||||
@GetMapping("/api/user/account/acwing/acapp/receive_code/") |
||||
public JSONObject receiveCode(@RequestParam Map<String,String> data) { |
||||
String code = data.get("code"); |
||||
String state = data.get("state"); |
||||
return acappService.receiveCode(code,state); |
||||
} |
||||
|
||||
|
||||
} |
||||
|
@ -0,0 +1,27 @@ |
||||
package com.kob.backend.controller.user.account.acwing; |
||||
|
||||
import com.alibaba.fastjson.JSONObject; |
||||
import com.kob.backend.service.user.account.acwing.WebService; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.RequestParam; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
|
||||
import java.util.Map; |
||||
|
||||
@RestController |
||||
public class WebController { |
||||
@Autowired |
||||
private WebService webService; |
||||
|
||||
@GetMapping("/api/user/account/acwing/web/apply_code/") |
||||
public JSONObject applyCode() { |
||||
return webService.applyCode(); |
||||
} |
||||
@GetMapping("/api/user/account/acwing/web/receive_code/") |
||||
public JSONObject receiveCode(@RequestParam Map<String,String> data) { |
||||
String code = data.get("code"); |
||||
String state = data.get("state"); |
||||
return webService.receiveCode(code,state); |
||||
} |
||||
} |
@ -0,0 +1,136 @@ |
||||
package com.kob.backend.service.impl.user.account.acwing; |
||||
|
||||
import com.alibaba.fastjson.JSON; |
||||
import com.alibaba.fastjson.JSONObject; |
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
||||
import com.kob.backend.mapper.UserMapper; |
||||
import com.kob.backend.pojo.User; |
||||
import com.kob.backend.service.impl.user.account.acwing.utils.HttpClientUtil; |
||||
import com.kob.backend.service.user.account.acwing.AcappService; |
||||
import com.kob.backend.utils.JwtUtil; |
||||
import org.apache.http.NameValuePair; |
||||
import org.apache.http.message.BasicNameValuePair; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.data.redis.core.RedisTemplate; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import java.io.UnsupportedEncodingException; |
||||
import java.net.URLEncoder; |
||||
import java.time.Duration; |
||||
import java.util.ArrayList; |
||||
import java.util.LinkedList; |
||||
import java.util.List; |
||||
import java.util.Random; |
||||
|
||||
@Service |
||||
public class AcappServiceImpl implements AcappService { |
||||
private static final String appId = "3357"; |
||||
private static final String appSecret = "f343ff7eeaa649d2a257bffac0a9323a"; |
||||
private static final String redirectUri = "https://kob.bnblogs.cc/api/user/account/acwing/acapp/receive_code/"; |
||||
private static final String applyAccessTokenUrl = "https://www.acwing.com/third_party/api/oauth2/access_token/"; |
||||
private static final String getUserInfoUrl = "https://www.acwing.com/third_party/api/meta/identity/getinfo/"; |
||||
private static final Random random = new Random(); |
||||
|
||||
@Autowired |
||||
private UserMapper userMapper; |
||||
|
||||
@Autowired |
||||
private RedisTemplate<String,String> redisTemplate; |
||||
@Override |
||||
public JSONObject applyCode() { |
||||
JSONObject resp = new JSONObject(); |
||||
resp.put("appid",appId); |
||||
try { |
||||
resp.put("redirect_uri", URLEncoder.encode(redirectUri,"UTF-8")); |
||||
} catch (UnsupportedEncodingException e) { |
||||
e.printStackTrace(); |
||||
resp.put("result","failed"); |
||||
return resp; |
||||
} |
||||
|
||||
resp.put("scope","userinfo"); |
||||
|
||||
StringBuilder state = new StringBuilder(); |
||||
for (int i = 0; i < 10; i++) { |
||||
state.append((char)(random.nextInt(10) + '0')); // 十位随机数字字符串
|
||||
} |
||||
resp.put("state",state.toString()); |
||||
resp.put("result","success"); |
||||
redisTemplate.opsForValue().set(state.toString(),"true"); // 将state值存入redis
|
||||
redisTemplate.expire(state.toString(), Duration.ofMinutes(10)); // 设置过期时间为10分钟
|
||||
return resp; |
||||
} |
||||
|
||||
@Override |
||||
public JSONObject receiveCode(String code, String state) { |
||||
JSONObject resp = new JSONObject(); |
||||
resp.put("result","failed"); |
||||
if (code == null || state == null) return resp; // 传入的code和state为空
|
||||
if (Boolean.FALSE.equals(redisTemplate.hasKey(state))) return resp; // redis中没有该state
|
||||
redisTemplate.delete(state); // 删除该state,只使用一次
|
||||
|
||||
// 获取accessToken
|
||||
List<NameValuePair> nameValuePairs = new LinkedList<>(); |
||||
nameValuePairs.add(new BasicNameValuePair("appid",appId)); |
||||
nameValuePairs.add(new BasicNameValuePair("secret",appSecret)); |
||||
nameValuePairs.add(new BasicNameValuePair("code",code)); |
||||
|
||||
String getString = HttpClientUtil.get(applyAccessTokenUrl,nameValuePairs); // 请求结果存入一个字符串
|
||||
|
||||
if (getString == null) return resp; |
||||
|
||||
JSONObject getResp = JSONObject.parseObject(getString); |
||||
String accessToken = getResp.getString("access_token"); |
||||
String openId = getResp.getString("openid"); |
||||
|
||||
if (accessToken == null || openId == null) return resp; |
||||
|
||||
QueryWrapper<User> qw = new QueryWrapper<>(); |
||||
qw.eq("openid",openId); |
||||
List<User> users = userMapper.selectList(qw); // 查询满足openid的用户是否存在
|
||||
if (!users.isEmpty()) { |
||||
User user = users.get(0); |
||||
String jwt = JwtUtil.createJWT(user.getId().toString()); |
||||
resp.put("result","success"); |
||||
resp.put("jwt_token",jwt); |
||||
return resp; |
||||
} |
||||
|
||||
// 如果不存在说明该用户没有登录过,需要根据上面的accessToken和openid向Acwing请求用户信息
|
||||
|
||||
nameValuePairs = new LinkedList<>(); |
||||
nameValuePairs.add(new BasicNameValuePair("access_token",accessToken)); |
||||
nameValuePairs.add(new BasicNameValuePair("openid",openId)); |
||||
|
||||
getString = HttpClientUtil.get(getUserInfoUrl,nameValuePairs); // 将请求结果存入字符串
|
||||
|
||||
if (getString == null) return resp; |
||||
getResp = JSONObject.parseObject(getString); |
||||
// 获得用户的用户名和头像
|
||||
String username = getResp.getString("username"); |
||||
String photo = getResp.getString("photo"); |
||||
|
||||
if (username == null || photo == null) return resp; |
||||
|
||||
// 避免新出现的用户重名
|
||||
for (int i = 0; i < 100; i++) { // 随机在后面添加以为数字
|
||||
QueryWrapper<User> queryWrapper = new QueryWrapper<>(); |
||||
queryWrapper.eq("username",username); |
||||
// 没有重名,直接退出
|
||||
if (userMapper.selectList(queryWrapper).isEmpty()) break; |
||||
username += (char)(random.nextInt(10) + '0'); |
||||
if (i == 99) return resp; // 小概率事件,太逆天,直接返回
|
||||
} |
||||
|
||||
// 根据获得的信息建立一个用户
|
||||
User user = new User(null,username,null,photo,null,openId); |
||||
userMapper.insert(user); |
||||
|
||||
String jwt = JwtUtil.createJWT(user.getId().toString()); |
||||
|
||||
resp.put("result","success"); |
||||
resp.put("jwt_token",jwt); |
||||
|
||||
return resp; |
||||
} |
||||
} |
@ -0,0 +1,138 @@ |
||||
package com.kob.backend.service.impl.user.account.acwing; |
||||
|
||||
import com.alibaba.fastjson.JSONObject; |
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
||||
import com.kob.backend.mapper.UserMapper; |
||||
import com.kob.backend.pojo.User; |
||||
import com.kob.backend.service.impl.user.account.acwing.utils.HttpClientUtil; |
||||
import com.kob.backend.service.user.account.acwing.WebService; |
||||
import com.kob.backend.utils.JwtUtil; |
||||
import org.apache.http.NameValuePair; |
||||
import org.apache.http.message.BasicNameValuePair; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.data.redis.core.RedisTemplate; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import java.io.UnsupportedEncodingException; |
||||
import java.net.URLEncoder; |
||||
import java.time.Duration; |
||||
import java.util.LinkedList; |
||||
import java.util.List; |
||||
import java.util.Random; |
||||
|
||||
@Service |
||||
public class WebServiceImpl implements WebService { |
||||
private static final String appId = "3357"; |
||||
private static final String appSecret = "f343ff7eeaa649d2a257bffac0a9323a"; |
||||
private static final String redirectUri = "https://kob.bnblogs.cc/user/account/acwing/web/receive_code/"; |
||||
private static final String applyAccessTokenUrl = "https://www.acwing.com/third_party/api/oauth2/access_token/"; |
||||
private static final String getUserInfoUrl = "https://www.acwing.com/third_party/api/meta/identity/getinfo/"; |
||||
private static final Random random = new Random(); |
||||
|
||||
@Autowired |
||||
private UserMapper userMapper; |
||||
|
||||
@Autowired |
||||
private RedisTemplate<String,String> redisTemplate; |
||||
|
||||
@Override |
||||
public JSONObject applyCode() { |
||||
JSONObject resp = new JSONObject(); |
||||
String encodeUrl=""; |
||||
try { |
||||
encodeUrl = URLEncoder.encode(redirectUri,"UTF-8"); |
||||
} catch (UnsupportedEncodingException e) { |
||||
e.printStackTrace(); |
||||
resp.put("result","failed"); |
||||
return resp; |
||||
} |
||||
|
||||
StringBuilder state = new StringBuilder(); |
||||
for (int i = 0; i < 10; i++) { |
||||
state.append((char)(random.nextInt(10) + '0')); // 十位随机数字字符串
|
||||
} |
||||
resp.put("result","success"); |
||||
redisTemplate.opsForValue().set(state.toString(),"true"); // 将state值存入redis
|
||||
redisTemplate.expire(state.toString(), Duration.ofMinutes(10)); // 设置过期时间为10分钟
|
||||
|
||||
String applyCodeUrl = "https://www.acwing.com/third_party/api/oauth2/web/authorize/?appid=" + appId |
||||
+ "&redirect_uri=" + encodeUrl |
||||
+ "&scope=userinfo" |
||||
+ "&state=" + state; |
||||
resp.put("apply_code_url",applyCodeUrl); |
||||
return resp; |
||||
} |
||||
|
||||
@Override |
||||
public JSONObject receiveCode(String code, String state) { |
||||
JSONObject resp = new JSONObject(); |
||||
resp.put("result","failed"); |
||||
if (code == null || state == null) return resp; // 传入的code和state为空
|
||||
if (Boolean.FALSE.equals(redisTemplate.hasKey(state))) return resp; // redis中没有该state
|
||||
redisTemplate.delete(state); // 删除该state,只使用一次
|
||||
|
||||
// 获取accessToken
|
||||
List<NameValuePair> nameValuePairs = new LinkedList<>(); |
||||
nameValuePairs.add(new BasicNameValuePair("appid",appId)); |
||||
nameValuePairs.add(new BasicNameValuePair("secret",appSecret)); |
||||
nameValuePairs.add(new BasicNameValuePair("code",code)); |
||||
|
||||
String getString = HttpClientUtil.get(applyAccessTokenUrl,nameValuePairs); // 请求结果存入一个字符串
|
||||
|
||||
if (getString == null) return resp; |
||||
|
||||
JSONObject getResp = JSONObject.parseObject(getString); |
||||
String accessToken = getResp.getString("access_token"); |
||||
String openId = getResp.getString("openid"); |
||||
|
||||
if (accessToken == null || openId == null) return resp; |
||||
|
||||
QueryWrapper<User> qw = new QueryWrapper<>(); |
||||
qw.eq("openid",openId); |
||||
List<User> users = userMapper.selectList(qw); // 查询满足openid的用户是否存在
|
||||
if (!users.isEmpty()) { |
||||
User user = users.get(0); |
||||
String jwt = JwtUtil.createJWT(user.getId().toString()); |
||||
resp.put("result","success"); |
||||
resp.put("jwt_token",jwt); |
||||
return resp; |
||||
} |
||||
|
||||
// 如果不存在说明该用户没有登录过,需要根据上面的accessToken和openid向Acwing请求用户信息
|
||||
|
||||
nameValuePairs = new LinkedList<>(); |
||||
nameValuePairs.add(new BasicNameValuePair("access_token",accessToken)); |
||||
nameValuePairs.add(new BasicNameValuePair("openid",openId)); |
||||
|
||||
getString = HttpClientUtil.get(getUserInfoUrl,nameValuePairs); // 将请求结果存入字符串
|
||||
|
||||
if (getString == null) return resp; |
||||
getResp = JSONObject.parseObject(getString); |
||||
// 获得用户的用户名和头像
|
||||
String username = getResp.getString("username"); |
||||
String photo = getResp.getString("photo"); |
||||
|
||||
if (username == null || photo == null) return resp; |
||||
|
||||
// 避免新出现的用户重名
|
||||
for (int i = 0; i < 100; i++) { // 随机在后面添加以为数字
|
||||
QueryWrapper<User> queryWrapper = new QueryWrapper<>(); |
||||
queryWrapper.eq("username",username); |
||||
// 没有重名,直接退出
|
||||
if (userMapper.selectList(queryWrapper).isEmpty()) break; |
||||
username += (char)(random.nextInt(10) + '0'); |
||||
if (i == 99) return resp; // 小概率事件,太逆天,直接返回
|
||||
} |
||||
|
||||
// 根据获得的信息建立一个用户
|
||||
User user = new User(null,username,null,photo,null,openId); |
||||
userMapper.insert(user); |
||||
|
||||
String jwt = JwtUtil.createJWT(user.getId().toString()); |
||||
|
||||
resp.put("result","success"); |
||||
resp.put("jwt_token",jwt); |
||||
|
||||
return resp; |
||||
} |
||||
} |
@ -0,0 +1,38 @@ |
||||
package com.kob.backend.service.impl.user.account.acwing.utils; |
||||
|
||||
|
||||
import org.apache.http.HttpEntity; |
||||
import org.apache.http.NameValuePair; |
||||
import org.apache.http.client.methods.CloseableHttpResponse; |
||||
import org.apache.http.client.methods.HttpGet; |
||||
import org.apache.http.client.utils.URIBuilder; |
||||
import org.apache.http.impl.client.CloseableHttpClient; |
||||
import org.apache.http.impl.client.HttpClients; |
||||
import org.apache.http.util.EntityUtils; |
||||
|
||||
import java.io.IOException; |
||||
import java.net.URISyntaxException; |
||||
import java.util.List; |
||||
|
||||
public class HttpClientUtil { |
||||
public static String get(String url, List<NameValuePair> params) { |
||||
URIBuilder uriBuilder = null; |
||||
try { |
||||
uriBuilder = new URIBuilder(url); |
||||
} catch (URISyntaxException e) { |
||||
e.printStackTrace(); |
||||
return null; |
||||
} |
||||
uriBuilder.setParameters(params); |
||||
|
||||
try (CloseableHttpClient client = HttpClients.createDefault()) { |
||||
HttpGet httpGet = new HttpGet(uriBuilder.build()); |
||||
CloseableHttpResponse response = client.execute(httpGet); |
||||
HttpEntity entity = response.getEntity(); |
||||
return EntityUtils.toString(entity); |
||||
} catch (IOException | URISyntaxException e) { |
||||
e.printStackTrace(); |
||||
return null; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,8 @@ |
||||
package com.kob.backend.service.user.account.acwing; |
||||
|
||||
import com.alibaba.fastjson.JSONObject; |
||||
|
||||
public interface AcappService { |
||||
JSONObject applyCode(); |
||||
JSONObject receiveCode(String code,String state); |
||||
} |
@ -0,0 +1,8 @@ |
||||
package com.kob.backend.service.user.account.acwing; |
||||
|
||||
import com.alibaba.fastjson.JSONObject; |
||||
|
||||
public interface WebService { |
||||
JSONObject applyCode(); |
||||
JSONObject receiveCode(String code,String state); |
||||
} |
@ -0,0 +1,42 @@ |
||||
<template> |
||||
<div></div> |
||||
</template> |
||||
|
||||
<script> |
||||
import $ from 'jquery'; |
||||
import router from '@/router/index' |
||||
import { useRoute } from "vue-router" |
||||
import { useStore } from "vuex"; |
||||
|
||||
export default { |
||||
setup() { |
||||
const myRouter = useRoute(); |
||||
const store= useStore(); |
||||
$.ajax({ |
||||
url: "https://kob.bnblogs.cc/api/user/account/acwing/web/receive_code/", |
||||
type: "GET", |
||||
data: { |
||||
code: myRouter.query.code, |
||||
state: myRouter.query.state, |
||||
}, |
||||
success: resp => { |
||||
if (resp.result === "success") { |
||||
console.log(resp); |
||||
// 保存jwt_token |
||||
localStorage.setItem("jwt_token",resp.jwt_token); |
||||
store.commit("updateToken",resp.jwt_token); |
||||
router.push({ name:"home" }); // 验证成功跳转到首页 |
||||
store.commit("updatePullingInfo",false); |
||||
}else { // 用户拒绝授权,跳转到注册页面 |
||||
router.push({ name:"register" }); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
|
||||
<style scoped> |
||||
|
||||
</style> |
Loading…
Reference in new issue