赞
踩
业务代码
- /**
- * 微信登录
- */
- @Override
- @Transactional(rollbackFor = Exception.class)
- public AjaxResult wxLogin(WeChatCodeRequest request, HttpServletRequest httpServletRequest) {
- String code = request.getCode();
- //通过code获取手机号
- JSONObject jsonObject = WechatUtil.getPhoneNumber(code);
- JSONObject js = (JSONObject) jsonObject.get("phone_info");
- String phoneNumber = (String) js.get("phoneNumber");
- //对手机号进行判断,登录
- //剩下的是校验成功的情况
- if (iSysUserService.getLoginUserByPhone(phoneNumber) == null) {
- return AjaxResult.error("登录失败,用户不存在或不可用,请联系管理员注册");
- } else {
- AjaxResult ajax = new AjaxResult();
- //说明在User表中已经存在,则将二者绑定到一起,使用user信息进行登录
- redisCache.deleteObject(CacheConstants.CAPTCHA_CODE_KEY + phoneNumber);
- // LoginUser loginUser = tokenService.getLoginUser(httpServletRequest);
- LoginUser loginUser = iSysUserService.getLoginUserByPhone(phoneNumber);
- List<SysUserRole> sysUserRoles = sysUserRoleMapper.selectList(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, loginUser.getUserId()));
- List<SysRole> collect = sysUserRoles.stream().map(i -> {
- //拿着roleid查询role
- SysRole sysRole = roleMapper.selectRoleById(i.getRoleId());
- return sysRole;
- }).collect(Collectors.toList());
- LambdaUpdateWrapper<SysUser> uw = new LambdaUpdateWrapper<SysUser>()
- .set(SysUser::getLoginIp, ServletUtil.getClientIP(httpServletRequest))
- .set(SysUser::getLoginDate, new Date())
- .set(SysUser::getUpdateTime, new Date())
- .eq(SysUser::getPhonenumber, phoneNumber)
- .eq(SysUser::getStatus, "0")
- .eq(SysUser::getDelFlag, "0");
- iSysUserService.update(uw);
- // 生成token
- //设置角色
- loginUser.getUser().setRoles(collect);
- //设置权限
- // loginUser.setPermissions();
- String token = tokenService.createToken(loginUser);
- ajax.put(Constants.TOKEN, token);
- tokenService.setLoginUser(loginUser);
- return ajax;
- }
- }
tokenService工具类
- package mmm.crm.system.web.service;
-
- import java.util.HashMap;
- import java.util.Map;
- import java.util.concurrent.TimeUnit;
- import javax.servlet.http.HttpServletRequest;
-
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.stereotype.Component;
- import mmm.crm.common.constant.CacheConstants;
- import mmm.crm.common.constant.Constants;
- import mmm.crm.common.core.domain.model.LoginUser;
- import mmm.crm.common.core.redis.RedisCache;
- import mmm.crm.common.utils.ServletUtils;
- import mmm.crm.common.utils.StringUtils;
- import mmm.crm.common.utils.ip.AddressUtils;
- import mmm.crm.common.utils.ip.IpUtils;
- import mmm.crm.common.utils.uuid.IdUtils;
- import eu.bitwalker.useragentutils.UserAgent;
- import io.jsonwebtoken.Claims;
- import io.jsonwebtoken.Jwts;
- import io.jsonwebtoken.SignatureAlgorithm;
-
- /**
- * token验证处理
- */
- @Component
- public class TokenService {
- // 令牌自定义标识
- @Value("${token.header}")
- private String header;
-
- // 令牌秘钥
- @Value("${token.secret}")
- private String secret;
-
- // 令牌有效期(默认30分钟)
- @Value("${token.expireTime}")
- private int expireTime;
-
- protected static final long MILLIS_SECOND = 1000;
-
- protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
-
- private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
-
- @Autowired
- private RedisCache redisCache;
-
- /**
- * 获取用户身份信息
- *
- * @return 用户信息
- */
- public LoginUser getLoginUser(HttpServletRequest request) {
- // 获取请求携带的令牌
- String token = getToken(request);
- if (StringUtils.isNotEmpty(token)) {
- try {
- Claims claims = parseToken(token);
- // 解析对应的权限以及用户信息
- String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
- String userKey = getTokenKey(uuid);
- LoginUser user = redisCache.getCacheObject(userKey);
- return user;
- } catch (Exception e) {
- }
- }
- return null;
- }
-
- /**
- * 设置用户身份信息
- */
- public void setLoginUser(LoginUser loginUser) {
- if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken())) {
- refreshToken(loginUser);
- }
- }
-
- /**
- * 删除用户身份信息
- */
- public void delLoginUser(String token) {
- if (StringUtils.isNotEmpty(token)) {
- String userKey = getTokenKey(token);
- redisCache.deleteObject(userKey);
- }
- }
-
- /**
- * 创建令牌
- *
- * @param loginUser 用户信息
- * @return 令牌
- */
- public String createToken(LoginUser loginUser) {
- String token = IdUtils.fastUUID();
- loginUser.setToken(token);
- setUserAgent(loginUser);
- refreshToken(loginUser);
-
- Map<String, Object> claims = new HashMap<>();
- claims.put(Constants.LOGIN_USER_KEY, token);
- return createToken(claims);
- }
-
- /**
- * 验证令牌有效期,相差不足20分钟,自动刷新缓存
- *
- * @param loginUser
- * @return 令牌
- */
- public void verifyToken(LoginUser loginUser) {
- long expireTime = loginUser.getExpireTime();
- long currentTime = System.currentTimeMillis();
- if (expireTime - currentTime <= MILLIS_MINUTE_TEN) {
- refreshToken(loginUser);
- }
- }
-
- /**
- * 刷新令牌有效期
- *
- * @param loginUser 登录信息
- */
- public void refreshToken(LoginUser loginUser) {
-
- loginUser.setLoginTime(System.currentTimeMillis());
- loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
- // 根据uuid将loginUser缓存
- String userKey = getTokenKey(loginUser.getToken());
- redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
- }
-
- /**
- * 设置用户代理信息
- *
- * @param loginUser 登录信息
- */
- public void setUserAgent(LoginUser loginUser) {
- UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
- String ip = IpUtils.getIpAddr();
- loginUser.setIpaddr(ip);
- loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
- loginUser.setBrowser(userAgent.getBrowser().getName());
- loginUser.setOs(userAgent.getOperatingSystem().getName());
- }
-
- /**
- * 从数据声明生成令牌
- *
- * @param claims 数据声明
- * @return 令牌
- */
- private String createToken(Map<String, Object> claims) {
- String token = Jwts.builder()
- .setClaims(claims)
- .signWith(SignatureAlgorithm.HS512, secret).compact();
- return token;
- }
-
- /**
- * 从令牌中获取数据声明
- *
- * @param token 令牌
- * @return 数据声明
- */
- private Claims parseToken(String token) {
- return Jwts.parser()
- .setSigningKey(secret)
- .parseClaimsJws(token)
- .getBody();
- }
-
- /**
- * 从令牌中获取用户名
- *
- * @param token 令牌
- * @return 用户名
- */
- public String getUsernameFromToken(String token) {
- Claims claims = parseToken(token);
- return claims.getSubject();
- }
-
- /**
- * 获取请求token
- *
- * @param request
- * @return token
- */
- public String getToken(HttpServletRequest request) {
- String token = request.getHeader(header);
- if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) {
- token = token.replace(Constants.TOKEN_PREFIX, "");
- }
- return token;
- }
-
- private String getTokenKey(String uuid) {
- return CacheConstants.LOGIN_TOKEN_KEY + uuid;
- }
- }
微信登录工具类
package mmm.crm.common.utils; import cn.hutool.http.Header; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.google.common.net.HttpHeaders; import com.google.gson.Gson; import com.google.gson.JsonObject; import lombok.extern.log4j.Log4j; import mmm.crm.common.utils.http.HttpUtils; import mmm.crm.common.utils.sign.Base64; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.client.RestTemplate; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import javax.servlet.FilterConfig; import javax.xml.bind.ValidationException; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.*; import java.security.spec.InvalidParameterSpecException; import java.util.Arrays; import java.util.HashMap; import java.util.Map; /** * @Author:XGY * @Date:2023/4/24 18:14 */ public class WechatUtil { public static JSONObject getSessionKeyOrOpenId(String code) throws IOException { //微信端登录code String wxCode = code; String requestUrl = "https://api.weixin.qq.com/sns/jscode2session"; Map<String, String> requestUrlParam = new HashMap<>(); //小程序appId requestUrlParam.put("appid", "wx88c4501ad86e1174"); //小程序secret requestUrlParam.put("secret", "c08515ced6cd60e976028be5d0d43498"); //小程序端返回的code requestUrlParam.put("js_code", wxCode); //默认参数 requestUrlParam.put("grant_type", "authorization_code"); //发送post请求读取调用微信接口获取openid用户唯一标识 JSONObject jsonObject = JSON.parseObject(HttpClientUtil.doPost(requestUrl, requestUrlParam)); return jsonObject; } public static com.alibaba.fastjson2.JSONObject getUserInfo(String encryptedData, String sessionKey, String iv) { // 被加密的数据 byte[] dataByte = Base64.decode(encryptedData); // 加密秘钥 byte[] keyByte = Base64.decode(sessionKey); // 偏移量 byte[] ivByte = Base64.decode(iv); try { // 如果密钥不足16位,那么就补足. 这个if 中的内容很重要 int base = 16; if (keyByte.length % base != 0) { int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0); byte[] temp = new byte[groups * base]; Arrays.fill(temp, (byte) 0); System.arraycopy(keyByte, 0, temp, 0, keyByte.length); keyByte = temp; } // 初始化 Security.addProvider(new BouncyCastleProvider()); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC"); SecretKeySpec spec = new SecretKeySpec(keyByte, "AES"); AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES"); parameters.init(new IvParameterSpec(ivByte)); cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化 byte[] resultByte = cipher.doFinal(dataByte); if (null != resultByte && resultByte.length > 0) { String result = new String(resultByte, "UTF-8"); return JSON.parseObject(result); } } catch (Exception e) { new Exception(e); } return null; } // public static String getPhone(String code) throws ValidationException, IOException { // final String appID = "wx88c4501ad86e1174"; // final String appSecret = "c08515ced6cd60e976028be5d0d43498"; // //使用appid和密钥获取access_token String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appID + "&secret=" + appSecret; String s = HttpUtils.sendGet(url); JSONObject jsonObject = HttpUtils.doGetJson(url); // //使用access_token和code获取手机号 // JSONObject accessToken = getAccessToken(appID, appSecret); // String url1 = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken.getString("access_token"); // JSONObject data = new JSONObject(); // data.put("code", code); // String phoneNumber = null; // try { // JSONObject jsonObject1 = HttpUtils.doPost(url1, code); // JSONObject phone_info = (JSONObject) jsonObject1.get("phone_info"); // phoneNumber = phone_info.getString("phoneNumber"); // } catch (Exception e) { // throw new RuntimeException(e); // } // return phoneNumber; // } // public static JSONObject getAccessToken(String appid, String secretKey) { // String result = null; // try { // String baseUrl = "https://api.weixin.qq.com/cgi-bin/token"; // HashMap<String, Object> requestParam = new HashMap<>(); // // 小程序 appId // requestParam.put("grant_type", "client_credential"); // // 小程序唯一凭证id // requestParam.put("appid", appid); // // 小程序 appSecret(小程序的唯一凭证密钥) // requestParam.put("secret", secretKey); // // 发送GET请求读取调用微信接口获取openid用户唯一标识 // result = HttpUtil.get(baseUrl, requestParam); // } catch (Exception e) { // e.printStackTrace(); // } // return JSONObject.parseObject(result); // } public static String getAccessTokenOne(String appId,String appSecret) { String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret; System.out.println("request user info from url: {" + url + "}"); JsonObject accessTokenInfo = null; try { DefaultHttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(url); CloseableHttpResponse httpResponse = httpClient.execute(httpGet); HttpEntity entity = httpResponse.getEntity(); String response = EntityUtils.toString(entity, "utf-8"); //LOGGER.error("获取Token-------------------"+response); Gson token_gson = new Gson(); accessTokenInfo = token_gson.fromJson(response, JsonObject.class); return accessTokenInfo.get("access_token").toString().replaceAll("\"", ""); } catch (Exception ex) { System.out.println("fail to request wechat user info. [error={" + ex + "}]"); } return ""; } /** * 请求微信接口服务,用code换取用户手机号(每个code只能使用一次,code的有效期为5min) * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/phonenumber/phonenumber.getPhoneNumber.html * * @param code * @param accessToken * @return */ public static JSONObject getPhoneNumber(String code) { final String appID = "wx88c4501ad86e1174"; final String appSecret = "c08515ced6cd60e976028be5d0d43498"; String accessTokenOne = getAccessTokenOne(appID, appSecret); String result = null; try { // 接口调用凭证:accessToken String baseUrl = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessTokenOne; HashMap<String, Object> requestParam = new HashMap<>(); // 手机号调用凭证 requestParam.put("code", code); // 发送post请求读取调用微信接口获取openid用户唯一标识 String jsonStr = JSONUtil.toJsonStr(requestParam); HttpResponse response = HttpRequest.post(baseUrl) .header(Header.CONTENT_ENCODING, "UTF-8") // 发送json数据需要设置contentType .header(Header.CONTENT_TYPE, "application/x-www-form-urlencoded") .body(jsonStr) .execute(); if (response.getStatus() == HttpStatus.SUCCESS) { result = response.body(); } } catch (Exception e) { e.printStackTrace(); } return JSONObject.parseObject(result); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。