Springboot 를 이용 하여 Jwt 인증 을 실현 하 는 예시 코드
14574 단어 SpringbootJwt인증
Shiro 통합 JWT 에 대해 서 는 여 기 를 볼 수 있 습 니 다Springboot Shiro+JWT 인증 실현
개술
개념 적 인 내용 이 인터넷 에 많 기 때문에 상세 하 게 소개 하지 않 겠 습 니 다.
구체 적 으로 는 여 기 를 볼 수 있다.
나 는 몇 가지 중점 을 총 결 했다.
JWT,전 칭 JSon Web Token,영패 인증 방식
생김새:
머리:서명 알고리즘 과 토 큰 유형(이것 이 바로 JWT)을 넣 습 니 다4.567917.부하:당신 이 토 큰 에 첨부 한 정보:예 를 들 어 사용자 의 id,사용자 의 전화번호 등 이 있 습 니 다.그러면 나중에 토 큰 을 검증 한 후에 바로 여기 서 정 보 를 얻 을 수 있 습 니 다.데이터 베 이 스 를 찾 지 않 아 도 됩 니 다서명:영패 추가 용안전성:부하 에 있 는 내용 은 모두 BASE 64 로 처리 되 기 때문에 비밀 성 이 없다(BASE 64 는 대칭 적 이기 때문이다).그러나 서명 인증 으로 인해 다른 사람들 은 데 이 터 를 위조 하기 어렵다.그러나 이것 은 민감 한 정보,예 를 들 어 비밀 번 호 를 부하 에 넣 으 면 안 된다 는 것 을 의미한다.왜냐하면 이런 것 은 다른 사람 이 직접 볼 수 있 지만 사용자 id 와 같은 것 은 상관없다.
작업 흐름
로그 인 단계
사용자 가 처음으로 로그 인 하여 계 정 비밀 번 호 를 비교 하여 로그 인 성공 여 부 를 판단 합 니 다.로그 인 에 성공 하면 jwt 문자열 을 생 성 한 다음 에 추가 정 보 를 넣 어 클 라 이언 트 에 게 되 돌려 줍 니 다.
이 jwt 문자열 에는 사용자 와 관련 된 정보 가 포함 되 어 있 습 니 다.예 를 들 어 이 사용자 가 누구 인지,그의 id 가 얼마 인지,이 영패 의 유효 시간 이 얼마 인지 등 입 니 다.다음 사용자 가 로그 인 할 때 이 영패 도 함께 가 져 가 야 합 니 다.
인증 단계
여 기 는 전단 과 통일 적 으로 약속 해 야 합 니 다.요청 을 할 때 지난번 token 을 요청 머리 에 있 는 한 위치 에 두 고 보 냅 니 다.백 엔 드 가 요청 을 받 은 후에 jwt 를 분석 하여 jwt 가 합 법 적 인지,위조 되 었 는 지,기한 이 지 났 는 지 검증 합 니 다.여기까지 검증 과정 이 완료 되 었 습 니 다.
그러나 서버 역시 검 증 된 jwt 에서 사용자 의 관련 정 보 를 얻어 데이터베이스 에 대한 조 회 를 줄 일 수 있다.
예 를 들 어 우 리 는'사용자 전화 번 호 를 통 해 사용자 의 잔액 을 조회 합 니 다'라 는 업무 가 있 습 니 다.
만약 에 우리 가 jwt 의 부하 에 전화번호 라 는 속성 을 미리 두 었 다 면 우 리 는 먼저 데이터 베 이 스 를 가서 사용자 id 에 따라 사용자 의 전화 번 호 를 조회 하고 전화 번 호 를 직접 받 은 다음 에 받 는 업무 논 리 를 수행 하 는 것 을 피 할 수 있 습 니 다.
유효기간
jwt 는 사용자 에 게 직접 주 는 것 이기 때문에 성공 적 인 jwt 를 검증 할 수 있다 면 로그 인 성공 으로 볼 수 있 습 니 다.따라서 jwt 에 만 료 시간 을 설정 하지 않 으 면 사용 자 는 이 jwt 를 저장 하면 영원히 로그 인 하 는 것 과 같 습 니 다.이것 은 안전 하지 않 습 니 다.만약 에 이 번호판 이 누설 되면그러면 서버 는 이 영패 소지 자의 접근 을 막 을 방법 이 없습니다.(이 영패 를 받 으 면 마음대로 신분 을 사칭 하여 방문 하 는 것 과 같 기 때문에)jwt 는 유효기간 이 있 습 니 다.보통 부하 부분 에 존재 합 니 다.다음은 jwt 를 생 성 하 는 자바 코드 입 니 다.
return JWT.create().withAudience(userId)
.withIssuedAt(new Date()) <----
.withExpiresAt(expiresDate) <----
.withClaim("sessionId", sessionId)
.withClaim("userName", userName)
.withClaim("realName", realName)
.sign(Algorithm.HMAC256(userId+"HelloLehr"));
실제 개발 에 서 는 영패 의 유효기간 이 짧 을 수록 안전 하 다.영패 가 자주 변 하기 때문에 어떤 영패 가 다른 사람 에 게 도용 되 더 라 도 곧 효력 을 잃 기 때문이다.그러나 유효기간 이 짧 으 면 사용자 체험 이 좋 지 않 을 수 있 기 때문에 이 럴 때 또 다른 영패 가 나타난다refresh token
영패 리 셋 의 유효기간 은 매우 길 것 입 니 다.영패 리 셋 이 기한 이 지나 지 않 았 다 면 다른 jwt 를 신청 할 수 있 습 니 다.로그 인 할 필요 가 없습니다.(그리고 이 과정 은 사용자 가 특정한 인 터 페 이 스 를 방문 할 때 자동 으로 완 성 됩 니 다.사용 자 는 영패 교체 가 느껴 지지 않 습 니 다)영패 리 셋 에 대한 구체 적 인 실 제 는 자세히 말씀 드 리 지 않 겠 습 니 다.(사실은 저도 XD 를 깊이 연구 한 적 이 없 기 때 문 입 니 다.)대비 세 션
전통 적 인 session 세 션 메커니즘 에서 서버 식별 사용 자 는 사용자 가 처음으로 서버 에 접 근 했 을 때 사용자 에 게 sessionId 를 주 고 사용자 가 대응 하 는 세 션 기록 을 서버 에 두 었 다가 매번 sessionId 를 통 해 대응 하 는 세 션 기록 을 찾 았 다.이렇게 하면 모든 데이터 가 서버 에 존재 하 는 것 은 안전 하지만 분포 식 응용 에 있어 서 는 session 공유 문 제 를 고려 해 야 합 니 다.그렇지 않 으 면 같은 사용자 의 session Id 요청 이 다른 서버 에 자동 으로 배정 되면 효력 을 잃 는 것 과 같 습 니 다.
그리고 Jwt 는 로그 인 인증 에 사용 할 수 있 을 뿐만 아니 라 해당 하 는 데 이 터 를 사용자 에 게 되 돌려 주 었 습 니 다.서명 을 통 해 데이터 의 진실성 을 확보 합 니 다.이 응용 프로그램의 각 서버 에 통 일 된 검증 방법 이 있 습 니 다.검증 을 통과 할 수 있다 면 당신 의 번호판 이 믿 을 만하 다 는 것 을 설명 할 수 있 습 니 다.저 는 당신 의 영패 에서 당신 의 정 보 를 얻 을 수 있 습 니 다.당신 이 누구 인지 알 수 있 습 니 다.서버 의 압력 을 줄 이 고 분포 식 응용 에 도 더욱 우호 적 입 니 다.(서버 session 의 분포 식 저장 문 제 는 걱정 하지 않 아 도 되 니까)
통합 Springboot
자바-jwt 패키지 가 져 오기
가 져 오기
java-jwt
가방:이 가방 에는 일련의 jwt 작업 api 가 구현 되 어 있 습 니 다.
만약 당신 이 Maven 유저 라면:
pom.xml 에 쓰기
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.3</version>
</dependency>
만약 당신 이 Gradle 유저 라면:build.gradle 에 쓰기
compile group: 'com.auth0', name: 'java-jwt', version: '3.8.3'
만약 당신 이 다른 유저 라면:maven 중앙 창고 주소완 일 봉 사내 블 로그
도구 클래스 의 작성
코드 는 다음 과 같 습 니 다:
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
/**
* @author Lehr
* @create: 2020-02-04
*/
public class JwtUtils {
/**
: id
:
:30
: : ,
: id
*/
public static String createToken(String userId,String realName, String userName) {
Calendar nowTime = Calendar.getInstance();
nowTime.add(Calendar.MINUTE,30);
Date expiresDate = nowTime.getTime();
return JWT.create().withAudience(userId) //
.withIssuedAt(new Date()) //
.withExpiresAt(expiresDate) //
.withClaim("userName", userName) // ,
.withClaim("realName", realName)
.sign(Algorithm.HMAC256(userId+"HelloLehr")); //
}
/**
* , secret id
* @param token
* @throws TokenUnavailable
*/
public static void verifyToken(String token, String secret) throws TokenUnavailable {
DecodedJWT jwt = null;
try {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret+"HelloLehr")).build();
jwt = verifier.verify(token);
} catch (Exception e) {
//
// ,
throw new TokenUnavailable();
}
}
/**
*
*/
public static String getAudience(String token) throws TokenUnavailable {
String audience = null;
try {
audience = JWT.decode(token).getAudience().get(0);
} catch (JWTDecodeException j) {
// token
throw new TokenUnavailable();
}
return audience;
}
/**
*
*/
public static Claim getClaimByName(String token, String name){
return JWT.decode(token).getClaim(name);
}
}
작은 설명:jwt 생 성 시 암호 화 및 검증 방법:
jwt 의 검증 은 사실 jwt 의 마지막 부분(서명 부분)을 검증 하 는 것 이다.여기에 서명 한 암호 화 방식 을 지정 할 때 암호 화 된 문자열 도 들 어 왔 기 때문에 검증 할 때 암호 화 알고리즘 을 알 아야 할 뿐만 아니 라 이 문자열 을 얻어 야 복호화 에 성공 하고 안전성 을 높 일 수 있 습 니 다.제 가 사용 하 는 것 은 id 입 니 다.비교적 간단 합 니 다.만약 에 더 안전 하고 싶다 면 사용자 비밀 번 호 를 이 암호 화 문자열 로 사용 할 수 있 습 니 다.그러면 이 업무 코드 가 누설 되 더 라 도 큰 안전 문 제 를 일 으 키 지 않 을 것 입 니 다.(제 id 는 누구나 알 고 있 기 때문에 토 큰 은 위 조 될 수 있 습 니 다.그러나 비밀번호 로 바 꾸 면 데이터 베이스 가 무사 하면 아무 도 모 릅 니 다)
부하 획득 방법:
누 군 가 는 이상 하 게 생각 할 수 있 습 니 다.왜 복호화 가 필요 하지 않 고 verify 없 이 부하 에 있 는 내용 을 얻 을 수 있 습 니까?이 유 는 원래 부하 가 Base 64 로 처리 되 었 을 뿐 암호 성 이 없 기 때문에 그 값 을 직접 얻 을 수 있 습 니 다.그러나 이 값 의 진실성 을 믿 을 수 있 는 지 없 는 지 는 검증 을 통과 할 수 있 는 지 를 봐 야 합 니 다.마지막 서명 부분 은 앞 머리 와 부하 내용 과 관련 이 있 기 때문에 서명 이 검증 되면그럼 앞의 부하 가 바 뀌 지 않 았 다 는 거 야.
주해 류 의 작성
controller 층 의 모든 방법 에 있어 서 이 주 해 를 사용 하여 이 방법 에 접근 할 때 token 을 휴대 해 야 하 는 지 여 부 를 결정 할 수 있 습 니 다.기본 값 은 모든 검사 이기 때문에 일부 특수 인터페이스 에 대해 서 는 검증 면제 주 해 를 가 져 야 합 니 다.
인증 면제 주해
4.567914.인증 건 너 뛰 기,보통 입구 방법 에서 이 걸 사용 합 니 다.예 를 들 어 로그 인 인터페이스 등 입 니 다.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Lehr
* @create: 2020-02-03
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PassToken {
boolean required() default true;
}
차단기 작성설정 클래스
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author lehr
*/
@Configuration
public class JwtInterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//
registry.addInterceptor(authenticationInterceptor())
.addPathPatterns("/**");
}
@Bean
public JwtAuthenticationInterceptor authenticationInterceptor() {
return new JwtAuthenticationInterceptor();
}
}
차단기
import com.auth0.jwt.interfaces.Claim;
import com.imlehr.internship.annotation.PassToken;
import com.imlehr.internship.dto.AccountDTO;
import com.imlehr.internship.exception.NeedToLogin;
import com.imlehr.internship.exception.UserNotExist;
import com.imlehr.internship.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Map;
/**
* @author Lehr
* @create: 2020-02-03
*/
public class JwtAuthenticationInterceptor implements HandlerInterceptor {
@Autowired
AccountService accountService;
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
// token jwt token
String token = httpServletRequest.getHeader("token");
//
if (!(object instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) object;
Method method = handlerMethod.getMethod();
// passtoken ,
if (method.isAnnotationPresent(PassToken.class)) {
PassToken passToken = method.getAnnotation(PassToken.class);
if (passToken.required()) {
return true;
}
}
//
else {
System.out.println(" jwt ");
//
if (token == null) {
// , token ,
throw new NeedToLogin();
}
// token user Name
String userId = JwtUtils.getAudience(token);
// user ,
AccountDTO user = accountService.getByUserName(userId);
if (user == null) {
//
throw new UserNotExist();
}
// token
JwtUtils.verifyToken(token, userId)
//
String userName = JwtUtils.getClaimByName(token, "userName").asString();
String realName = JwtUtils.getClaimByName(token, "realName").asString();
// attribute
request.setAttribute("userName", userName);
request.setAttribute("realName", realName);
return true;
}
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object o, Exception e) throws Exception {
}
}
이 코드 의 실행 논 리 는 대략 다음 과 같다.목표 방법 에 주해 가 있 습 니까?PassToken 이 있 으 면 뒤의 인증 을 실행 하지 않 고 바로 실행 합 니 다.그렇지 않 으 면 모두 검증 이 필요 합 니 다4.567917.검증 시작:token 이 있 습 니까?없다그러면 오 류 를 되 돌려 줍 니 다.
4.567917.token 의 audience 에서 발급 대상 을 얻 고 이 사용자 가 있 는 지 확인 합 니 다(클 라 이언 트 가 조작 할 수 있 고 이 사용자 의 계 정 이 동결 되 었 을 수도 있 습 니 다).사용자 의 논 리 를 보면 Service 방법 을 직접 비교 하면 됩 니 다
여기 서 두 개의 인 터 페 이 스 를 설계 했다.로그 인 과 이름 조회 로 하나의 미니 업 무 를 모 의 했다.그 중에서 후 자 는 로그 인 한 후에 야 사용 할 수 있 고 대체적으로 다음 과 같다.
로그 인 코드
/**
* : , ,
* jwt
*
* @return
* @throws LoginFailed LoginFailed
*/
@PassToken
@GetMapping(value = "/login")
public AccountVO login(String userName, String password) throws LoginFailed{
try{
service.login(userName,password);
}
catch (AuthenticationException e)
{
throw new LoginFailed();
}
// ,
AccountVO account = accountService.getAccountByUserName(userName);
// token
String jwtToken = JwtUtils.createToken(account);
// token accountVO
account.setToken(jwtToken);
return account;
}
비 즈 니스 코드로그 인 이 필요 한 인 터 페 이 스 를 열거 합 니 다.
@GetMapping(value = "/username")
public String checkName(HttpServletRequest req) {
//
String name = (String) req.getAttribute("userName");
return name;
}
Springboot 를 이용 하여 Jwt 인증 을 실현 하 는 예제 코드 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 Springboot Jwt 인증 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[MeU] Hashtag 기능 개발➡️ 기존 Tag 테이블에 존재하지 않는 해시태그라면 Tag , tagPostMapping 테이블에 모두 추가 ➡️ 기존에 존재하는 해시태그라면, tagPostMapping 테이블에만 추가 이후에 개발할 태그 기반 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.