springboot 과 redis 를 기반 으로 단일 로그 인 을 실현 합 니 다.

본 논문 의 사례 는 springboot 과 redis 를 바탕 으로 단일 로그 인 을 실현 하 는 구체 적 인 코드 를 공유 하여 여러분 께 참고 하 시기 바 랍 니 다.구체 적 인 내용 은 다음 과 같 습 니 다.
1.구체 적 인 암호 화 및 복호화 방법

package com.example.demo.util;

import com.google.common.base.Strings;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;

/**
 * Create by zhuenbang on 2018/12/3 11:27
 */
public class AESUtil {
 private static final String defaultKey = "7bf72345-6266-4381-a4d3-988754c5f9d1";
 /** 
 * @Description:   
 * @Param: 
 * @returns: java.lang.String 
 * @Author: zhuenbang
 * @Date: 2018/12/3 11:33
 */
 public static String encryptByDefaultKey(String content) throws Exception {
 return encrypt(content, defaultKey);
 }

 
 /** 
 * @Description:    
 * @Param: 
 * @returns: java.lang.String 
 * @Author: zhuenbang
 * @Date: 2018/12/3 11:30
 */
 public static String decryptByDefaultKey(String encryptStr) throws Exception {
 return decrypt(encryptStr, defaultKey);
 }

 /**
 * AES   base 64 code
 *
 * @param content       
 * @param encryptKey     
 * @return     base 64 code
 * @throws Exception
 */

 public static String encrypt(String content, String encryptKey) throws Exception {
 return base64Encode(aesEncryptToBytes(content, encryptKey));

 }

 /**
 * AES  
 *
 * @param content       
 * @param encryptKey     
 * @return     byte[]
 * @throws Exception
 */

 private static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {

 KeyGenerator kgen = KeyGenerator.getInstance("AES");

 SecureRandom random;
 if (System.getProperty("os.name").toLowerCase().contains("linux")) {
 random = SecureRandom.getInstance("SHA1PRNG");
 } else {
 random = new SecureRandom();
 }

 random.setSeed(encryptKey.getBytes());
 kgen.init(128, random);

 Cipher cipher = Cipher.getInstance("AES");

 cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));


 return cipher.doFinal(content.getBytes("utf-8"));

 }

 /**
 * base 64   
 *
 * @param bytes     byte[]
 * @return     base 64 code
 */

 private static String base64Encode(byte[] bytes) {

 return new BASE64Encoder().encode(bytes);

 }
 
 /**
 *  base 64 code AES  
 *
 * @param encryptStr     base 64 code
 * @param decryptKey     
 * @return     string
 * @throws Exception
 */

 public static String decrypt(String encryptStr, String decryptKey) throws Exception {

 return Strings.isNullOrEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey);

 }
 
 /**
 * AES  
 *
 * @param encryptBytes     byte[]
 * @param decryptKey     
 * @return     String
 * @throws Exception
 */
 private static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {

 KeyGenerator kgen = KeyGenerator.getInstance("AES");

 SecureRandom random;
 if (System.getProperty("os.name").toLowerCase().contains("linux")) {
 random = SecureRandom.getInstance("SHA1PRNG");
 } else {
 random = new SecureRandom();
 }
 random.setSeed(decryptKey.getBytes());

 kgen.init(128, random);


 Cipher cipher = Cipher.getInstance("AES");

 cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));

 byte[] decryptBytes = cipher.doFinal(encryptBytes);


 return new String(decryptBytes);

 }

 /**
 * base 64   
 *
 * @param base64Code     base 64 code
 * @return     byte[]
 * @throws Exception
 */

 private static byte[] base64Decode(String base64Code) throws Exception {

 return Strings.isNullOrEmpty(base64Code) ? null : new BASE64Decoder().decodeBuffer(base64Code);

 }
}
2.여기 서 가 져 온 token 은 매우 관건 적 입 니 다.로그 인 할 때마다 새로운 token 을 생 성 합 니 다.token 은 userId 와 현재 시간 스탬프 에 따라 암호 화 됩 니 다.

@Override
 public String getToken(String userId) throws Exception {
 String token = AESUtil.encryptByDefaultKey(Joiner.on("_").join(userId, System.currentTimeMillis()));
 logger.debugv("token= {0}", token);
 redisService.set(UserKey.userAccessKey, userId, token);
 return token;
 }
3.복호화 방법 을 쓰 고 복호화 하여 사용자 id 를 꺼 낸 다음 차단기 에서 token 과 현재 로그 인 token 을 꺼 내 비교 합 니 다.

 @Override
 public String checkToken(String token) throws Exception {
 String userId = AESUtil.decryptByDefaultKey(token).split("_")[0];
 String currentToken = redisService.get(UserKey.userAccessKey, userId, String.class);
 logger.debugv("currentToken={0}", currentToken);
 if (StringUtils.isEmpty(currentToken)) {
  return null;
 }
 if (!token.equals(currentToken)) {
  return null;
 }
 return userId;
 }
4.차단기 에서 구체 적 으로 처리 합 니 다.여 기 는 주해 차단 을 사용 합 니 다.controller 에@Secured 차단기 가 있어 야 차단 합 니 다.

 @Autowired
 AuthTokenService authTokenService;
 @Override
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

 if (handler instanceof HandlerMethod) {
  HandlerMethod hm = (HandlerMethod) handler;
  Secured secured = hm.getMethodAnnotation(Secured.class);
  if (secured != null) {
  String authToken = request.getHeader(UserConstant.USER_TOKEN);
  if (StringUtils.isEmpty(authToken)) {
   render(response, CodeMsg.REQUEST_ILLEGAL);
   return false;
  }
  String userId = authTokenService.checkToken(authToken);
  if (StringUtils.isEmpty(userId)) {
   render(response, CodeMsg.LOGIN_FAILURE);
   return false;
  }
  }
  return true;
 }
 return true;
 }


private void render(HttpServletResponse response, CodeMsg cm) throws Exception {
 response.setContentType("application/json;charset=UTF-8");
 OutputStream out = response.getOutputStream();
 String str = JSON.toJSONString(Result.error(cm));
 out.write(str.getBytes("UTF-8"));
 out.flush();
 out.close();
 }
5.테스트 로그 인 인터페이스 와 테스트 단일 로그 인 인터페이스 작성

 /** 
 * @Description:      
 * @Param: 
 * @returns: com.example.demo.result.Result 
 * @Author: zhuenbang
 * @Date: 2018/12/3 12:05
 */
 @GetMapping("/login")
 public Result login() throws Exception {
 return authTokenService.login();
 }
 
 
 /** 
 * @Description:        @Secured          
 * @Param: 
 * @returns: com.example.demo.result.Result 
 * @Author: zhuenbang
 * @Date: 2018/12/3 12:35
 */
 @Secured
 @GetMapping("/testSSO")
 public Result testSSO() {
 return authTokenService.testSSO();
 }

      
 @Override
 public Result login() throws Exception {
 String userId = "123456";
 return Result.success(this.getToken(userId));
 }

 @Override
 public Result testSSO() {
 return Result.success("      ");
 }
postman 테스트

단일 로그 인 테스트

다시 로그 인 인 인 터 페 이 스 를 요청 한 후 token 인 터 페 이 스 를 바 꾸 지 않 습 니 다.그림 과 같 습 니 다.

이 방식 으로 단일 로그 인 을 실현 하 는 관건 은 userId 의 암호 화 와 복호화 에 따라 이 루어 지 는 것 이다.
github 주소:demo
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기