AuthServiceImpl.java 11 KB

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