/** * Copyright (c) 2018 人人开源 All rights reserved. * * https://www.renren.io * * 版权所有,侵权必究! */ package com.zt.security.controller; //import com.sun.deploy.net.URLEncoder; import com.zt.common.exception.ErrorCode; import com.zt.common.exception.RenException; import com.zt.common.servlet.Result; import com.zt.common.utils.IpUtils; import com.zt.core.context.User; import com.zt.core.context.UserContext; import com.zt.core.sys.model.SysUser; import com.zt.modules.log.enums.LoginOperationEnum; import com.zt.modules.log.enums.LoginStatusEnum; import com.zt.modules.log.model.SysLogLogin; import com.zt.modules.log.service.SysLogLoginService; import com.zt.modules.sys.enums.UserStatus; import com.zt.modules.sys.service.SysUserService; import com.zt.security.dto.LoginExDto; import com.zt.security.service.SysUserTokenService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import javax.crypto.*; import javax.crypto.spec.SecretKeySpec; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Date; /** * CAS 集成登录 * * @author hanjing */ @RestController @Api(tags = "CAS 集成登录") public class CasSsoController { @Autowired private SysUserService sysUserService; @Autowired private SysUserTokenService sysUserTokenService; @Autowired private SysLogLoginService sysLogLoginService; @PostMapping("public/casauth") @ApiOperation(value = "CAS 集成登录,验证用户信息。") public Result casAuth(HttpServletRequest request, @RequestBody LoginExDto login) { String username = ""; String ssoToken = login.getSsoToken(); try{ String password = "Edj&3G0L#sD"; // sso token 解密密钥,若修改此变量值,请对应修改 cas-client\src\main\webapp\index.jsp 中对应的变量值 byte[] res = new BASE64Decoder().decodeBuffer(ssoToken); byte[] decrypt = decrypt(res, password); ssoToken = URLDecoder.decode(new String(decrypt,"utf-8"), "UTF-8"); // 分隔 token 数据(用户名|#|创建登录跳转时的时间戳) String[] prams = ssoToken.split("\\|#\\|"); username = prams[0]; long create_time = Long.parseLong(prams[1]); long current_time = System.currentTimeMillis(); // 当前时间比ssoToken创建时间大于1分钟,则认为token无效,需要重新登录。 if(current_time - create_time > 2 * 60 * 1000){ throw new RenException(ErrorCode.TOKEN_INVALID); } }catch (Exception e){ // 抛出异常,token 无效。 throw new RenException(ErrorCode.TOKEN_INVALID); } // 用户信息 SysUser user = sysUserService.getByUsername(username); SysLogLogin log = new SysLogLogin(); log.setOperation(LoginOperationEnum.LOGIN.value()); log.setCreateDate(new Date()); log.setIp(IpUtils.getIpAddr(request)); log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT)); log.setIp(IpUtils.getIpAddr(request)); // 用户不存在 if (user == null) { log.setStatus(LoginStatusEnum.FAIL.value()); log.setCreatorName(login.getSsoToken()); sysLogLoginService.insert(log); throw new RenException(ErrorCode.ACCOUNT_PASSWORD_ERROR); } // 账号停用 if (user.getStatus() == UserStatus.DISABLE.getValue()) { log.setStatus(LoginStatusEnum.LOCK.value()); log.setCreator(user.getId()); log.setCreatorName(user.getUsername()); sysLogLoginService.insert(log); throw new RenException(ErrorCode.ACCOUNT_DISABLE); } // 登录成功 log.setStatus(LoginStatusEnum.SUCCESS.value()); log.setCreator(user.getId()); log.setCreatorName(user.getUsername()); sysLogLoginService.insert(log); return sysUserTokenService.createToken(user.getId(), "", ssoToken); } /** * AES加密字符串 * * @param content * 需要被加密的字符串 * @param password * 加密需要的密码 * @return 密文 */ public static byte[] encrypt(String content, String password) { try { KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者 kgen.init(128, new SecureRandom(password.getBytes()));// 利用用户密码作为随机数初始化出 //加密没关系,SecureRandom是生成安全随机数序列,password.getBytes()是种子,只要种子相同,序列就一样,所以解密只要有password就行 SecretKey secretKey = kgen.generateKey();// 根据用户密码,生成一个密钥 byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥,如果此密钥不支持编码,则返回 SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥 Cipher cipher = Cipher.getInstance("AES");// 创建密码器 byte[] byteContent = content.getBytes("utf-8"); cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化为加密模式的密码器 byte[] result = cipher.doFinal(byteContent);// 加密 return result; } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return null; } /** * 解密AES加密过的字符串 * * @param content * AES加密过过的内容 * @param password * 加密时的密码 * @return 明文 */ private static byte[] decrypt(byte[] content, String password) { try { KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者 kgen.init(128, new SecureRandom(password.getBytes())); SecretKey secretKey = kgen.generateKey();// 根据用户密码,生成一个密钥 byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥 SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥 Cipher cipher = Cipher.getInstance("AES");// 创建密码器 cipher.init(Cipher.DECRYPT_MODE, key);// 初始化为解密模式的密码器 byte[] result = cipher.doFinal(content); return result; // 明文 } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return null; } }