AuthServiceImpl.java 8.7 KB

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