springboot 과 redis 를 기반 으로 단일 로그 인 을 실현 합 니 다.
8601 단어 springbootredis단일 로그 인
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
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin Springboot -- 파트 14 사용 사례 REST로 전환하여 POST로 JSON으로 전환前回 前回 前回 記事 の は は で で で で で で を 使っ 使っ 使っ て て て て て リクエスト を を 受け取り 、 reqeustbody で 、 その リクエスト の ボディ ボディ を を 受け取り 、 関数 内部 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.