AuthServiceImpl.java 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. package cn.com.qmth.mps.service.impl;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import javax.crypto.Cipher;
  5. import javax.crypto.spec.IvParameterSpec;
  6. import javax.crypto.spec.SecretKeySpec;
  7. import org.apache.commons.lang3.StringUtils;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.stereotype.Service;
  10. import com.qmth.boot.core.exception.StatusException;
  11. import com.qmth.boot.core.security.service.AuthorizationService;
  12. import com.qmth.boot.tools.signature.SignatureType;
  13. import com.qmth.boot.tools.uuid.FastUUID;
  14. import cn.com.qmth.mps.bean.User;
  15. import cn.com.qmth.mps.config.SysProperty;
  16. import cn.com.qmth.mps.entity.UserEntity;
  17. import cn.com.qmth.mps.entity.WxappAccessTokenEntity;
  18. import cn.com.qmth.mps.enums.Role;
  19. import cn.com.qmth.mps.service.AuthService;
  20. import cn.com.qmth.mps.service.SessionService;
  21. import cn.com.qmth.mps.service.UserService;
  22. import cn.com.qmth.mps.service.WxappAccessTokenService;
  23. import cn.com.qmth.mps.util.ByteUtil;
  24. import cn.com.qmth.mps.util.HttpUtil;
  25. import cn.com.qmth.mps.util.SHA256;
  26. import cn.com.qmth.mps.vo.AdminLoginVo;
  27. import net.sf.json.JSONObject;
  28. import sun.misc.BASE64Decoder;
  29. @Service
  30. public class AuthServiceImpl implements AuthorizationService<User>, AuthService {
  31. @Autowired
  32. private UserService userService;
  33. @Autowired
  34. private SessionService sessionService;
  35. @Autowired
  36. private WxappAccessTokenService wxappAccessTokenService;
  37. @Autowired
  38. private SysProperty sysProperty;
  39. @Override
  40. public AdminLoginVo loginWxAppCode(String wxappCode) {
  41. Map<String, String> params = new HashMap<>();
  42. params.put("code", wxappCode);
  43. String ret;
  44. try {
  45. ret = HttpUtil.httpActionPost("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token="
  46. + wxappAccessTokenService.getWxappAccessToken().getAccessToken(), null, params);
  47. } catch (Exception e) {
  48. throw new StatusException("登录失败", e);
  49. }
  50. JSONObject jo = JSONObject.fromObject(ret);
  51. if (jo.getInt("errcode") != 0) {
  52. throw new StatusException("登录失败," + jo.getString("errmsg"));
  53. }
  54. UserEntity userEntity = userService.getByLoginName(jo.getJSONObject("phone_info").getString("purePhoneNumber"));
  55. if (userEntity == null) {
  56. throw new StatusException("微信所绑定手机号系统中不存在");
  57. }
  58. if (!userEntity.getEnable()) {
  59. throw new StatusException("该用户已禁用");
  60. }
  61. if (!userEntity.getRoleId().equals(Role.SECTION_LEADER.getId())) {
  62. throw new StatusException("该用户不是科组长");
  63. }
  64. User user = new User();
  65. user.setName(userEntity.getName());
  66. user.setSchoolId(userEntity.getSchoolId());
  67. user.setId(userEntity.getId());
  68. user.setRole(Role.getById(userEntity.getRoleId()));
  69. user.setAccessToken(FastUUID.get());
  70. user.buildKey();
  71. sessionService.userLogin(user);
  72. AdminLoginVo vo = new AdminLoginVo();
  73. vo.setAccessToken(user.getAccessToken());
  74. vo.setName(user.getName());
  75. vo.setSessionId(user.getSessionId());
  76. vo.setSchoolId(user.getSchoolId());
  77. vo.setRole(user.getRole());
  78. return vo;
  79. }
  80. @Override
  81. public AdminLoginVo loginAdmin(String loginName, String password) {
  82. UserEntity userEntity = userService.getByLoginName(loginName);
  83. if (userEntity == null) {
  84. throw new StatusException("账号不存在");
  85. }
  86. if (!userEntity.getEnable()) {
  87. throw new StatusException("该用户已禁用");
  88. }
  89. if (userEntity.getRoleId().equals(Role.SECTION_LEADER.getId())) {
  90. throw new StatusException("科组长无权限登录");
  91. }
  92. byte[] bytes = SHA256.encode(password);
  93. String encodePassword = ByteUtil.toHexAscii(bytes);
  94. if (!encodePassword.equals(userEntity.getPassword())) {
  95. throw new StatusException("密码错误");
  96. }
  97. User user = new User();
  98. user.setName(userEntity.getName());
  99. user.setSchoolId(userEntity.getSchoolId());
  100. user.setId(userEntity.getId());
  101. user.setRole(Role.getById(userEntity.getRoleId()));
  102. user.setAccessToken(FastUUID.get());
  103. user.buildKey();
  104. sessionService.userLogin(user);
  105. AdminLoginVo vo = new AdminLoginVo();
  106. vo.setAccessToken(user.getAccessToken());
  107. vo.setName(user.getName());
  108. vo.setSessionId(user.getSessionId());
  109. vo.setSchoolId(user.getSchoolId());
  110. vo.setRole(user.getRole());
  111. return vo;
  112. }
  113. @Override
  114. public void logout(User user) {
  115. sessionService.userLogout(user);
  116. }
  117. @Override
  118. public User findByIdentity(String identity, SignatureType type, String path) {
  119. User user = sessionService.getSessionUser(identity);
  120. return user;
  121. }
  122. @Override
  123. public boolean hasPermission(User user, String path) {
  124. sessionService.updateUserSession(user);
  125. return true;
  126. }
  127. @Override
  128. public void modifyWxappAccessToken() {
  129. WxappAccessTokenEntity token = wxappAccessTokenService.getWxappAccessToken();
  130. long now = System.currentTimeMillis();
  131. if (StringUtils.isEmpty(token.getAccessToken()) || token.getExpiresTime() - now <= 15 * 60 * 1000) {
  132. Map<String, String> params = new HashMap<>();
  133. params.put("appid", sysProperty.getWxappAppid());
  134. params.put("secret", sysProperty.getWxappSecret());
  135. params.put("grant_type", "client_credential");
  136. String ret;
  137. try {
  138. ret = HttpUtil.httpActionGet("https://api.weixin.qq.com/cgi-bin/token", null, params);
  139. } catch (Exception e) {
  140. throw new StatusException("获取失败", e);
  141. }
  142. JSONObject jo = JSONObject.fromObject(ret);
  143. if (jo.containsKey("errcode")) {
  144. throw new StatusException("获取失败," + jo.getString("errmsg"));
  145. }
  146. int ex = jo.getInt("expires_in");
  147. String at = jo.getString("access_token");
  148. token.setAccessToken(at);
  149. token.setExpiresTime(now + ex * 1000);
  150. wxappAccessTokenService.updateById(token);
  151. }
  152. }
  153. @Override
  154. public AdminLoginVo loginWxAppEncryptedData(String wxappCode, String encryptedData, String iv) {
  155. JSONObject jo=decrypt(encryptedData, iv, getSessionKey(wxappCode));
  156. String phone=jo.getString("purePhoneNumber");
  157. UserEntity userEntity = userService.getByLoginName(phone);
  158. if (userEntity == null) {
  159. throw new StatusException("微信所绑定手机号系统中不存在");
  160. }
  161. if (!userEntity.getEnable()) {
  162. throw new StatusException("该用户已禁用");
  163. }
  164. if (!userEntity.getRoleId().equals(Role.SECTION_LEADER.getId())) {
  165. throw new StatusException("该用户不是科组长");
  166. }
  167. User user = new User();
  168. user.setName(userEntity.getName());
  169. user.setSchoolId(userEntity.getSchoolId());
  170. user.setId(userEntity.getId());
  171. user.setRole(Role.getById(userEntity.getRoleId()));
  172. user.setAccessToken(FastUUID.get());
  173. user.buildKey();
  174. sessionService.userLogin(user);
  175. AdminLoginVo vo = new AdminLoginVo();
  176. vo.setAccessToken(user.getAccessToken());
  177. vo.setName(user.getName());
  178. vo.setSessionId(user.getSessionId());
  179. vo.setSchoolId(user.getSchoolId());
  180. vo.setRole(user.getRole());
  181. return vo;
  182. }
  183. private String getSessionKey(String wxappCode) {
  184. Map<String, String> params = new HashMap<>();
  185. params.put("appid", sysProperty.getWxappAppid());
  186. params.put("secret", sysProperty.getWxappSecret());
  187. params.put("js_code", wxappCode);
  188. params.put("grant_type", "authorization_code");
  189. String ret;
  190. try {
  191. ret = HttpUtil.httpActionGet("https://api.weixin.qq.com/sns/jscode2session", null, params);
  192. } catch (Exception e) {
  193. throw new StatusException("登录失败", e);
  194. }
  195. JSONObject jo = JSONObject.fromObject(ret);
  196. if (jo.containsKey("errcode")) {
  197. throw new StatusException("登录失败," + jo.getString("errmsg"));
  198. }
  199. return jo.getString("session_key");
  200. }
  201. private JSONObject decrypt(String encryptedData, String iv, String sessionKey){
  202. String cipherString = "AES/CBC/PKCS5Padding";
  203. String jsonStr;
  204. try {
  205. BASE64Decoder base64Decoder = new BASE64Decoder();
  206. /**
  207. * 小程序加密数据解密算法
  208. * https://developers.weixin.qq.com/miniprogram/dev/api/signature.html#wxchecksessionobject
  209. * 1.对称解密的目标密文为 Base64_Decode(encryptedData)。 2.对称解密秘钥 aeskey =
  210. * Base64_Decode(session_key), aeskey 是16字节。 3.对称解密算法初始向量
  211. * 为Base64_Decode(iv),其中iv由数据接口返回。
  212. */
  213. byte[] encryptedByte = base64Decoder.decodeBuffer(encryptedData);
  214. byte[] sessionKeyByte = base64Decoder.decodeBuffer(sessionKey);
  215. byte[] ivByte = base64Decoder.decodeBuffer(iv);
  216. /**
  217. * 以下为AES-128-CBC解密算法
  218. */
  219. SecretKeySpec skeySpec = new SecretKeySpec(sessionKeyByte, "AES");
  220. Cipher cipher = Cipher.getInstance(cipherString);
  221. IvParameterSpec ivParameterSpec = new IvParameterSpec(ivByte);
  222. cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivParameterSpec);
  223. byte[] original = cipher.doFinal(encryptedByte);
  224. jsonStr = new String(original);
  225. } catch (Exception e) {
  226. throw new StatusException("登录失败,信息有误 ",e);
  227. }
  228. JSONObject jsonObject = JSONObject.fromObject(jsonStr);
  229. return jsonObject;
  230. }
  231. }