JWT (JSON Web Token)는 네트워크 응용 프로그램 환경간에 클레임을 전달하기 위해 구현 된 JSON 기반 오픈 표준 (RFC 7519)입니다. 토큰은 작고 안전하도록 설계되었으며 특히 분산 사이트의 단일 사인 온 (SSO) 시나리오에 적합합니다. JWT 문은 일반적으로 자원 서버로부터 리소스를 획득 할 수 있도록 신분 공급자와 서비스 제공 업체간에 인증 된 사용자 신원 정보를 전달하는 데 사용됩니다. 또한 다른 비즈니스 논리에 필요한 추가 선언 정보를 추가 할 수도 있습니다. 토큰은 인증 또는 암호화에 직접 사용할 수도 있습니다.
일반적으로 API를 직접 노출시키는 것은 매우 위험합니다. 다른 것에 대해 이야기하지 않으면 기계에 직접 공격을 받으면 마실 수 있습니다. 일반적으로 특정 권한 수준은 API로 나눈 다음 사용자 인증을 수행하고 인증 결과에 따라 해당 API가 사용자에게 제공됩니다. 현재 몇 가지 주류 솔루션이 있습니다.
OAUTH는 사용자가 타사 애플리케이션이 제 3 자 애플리케이션에 사용자 이름과 비밀번호를 제공하지 않고 서비스에 사용자가 저장 한 개인 리소스 (예 : 사진, 비디오)에 액세스 할 수 있도록 허용하는 공개 인증 표준입니다.
OAUTH를 사용하면 사용자가 사용자 이름과 비밀번호 대신 토큰을 제공하여 특정 서비스 제공 업체에 저장 한 데이터에 액세스 할 수 있습니다. 각 토큰은 특정 제 3 자 시스템 (예 : 비디오 편집 웹 사이트)이 특정 기간 (예 : 다음 2 시간 이내에) 내에 특정 리소스 (예 : 특정 앨범의 비디오)에 액세스 할 수 있도록 권한을 부여합니다. 이러한 방식으로 OAUTH는 사용자가 타사 웹 사이트를 승인하여 모든 콘텐츠가 아닌 다른 서비스 제공 업체에 저장 한 특정 특정 정보에 액세스 할 수 있도록합니다.
쿠키 인증 메커니즘은 인증 요청을 위해 서버에서 세션 객체를 작성하고 동시에 클라이언트 브라우저에서 쿠키 객체를 만듭니다. 쿠키 객체는 클라이언트에게 가져와 서버의 세션 객체와 일치하여 상태 관리를 달성합니다. 기본적으로 브라우저를 닫으면 쿠키가 삭제됩니다. 그러나 쿠키의 만료 시간을 수정하여 쿠키를 일정 기간 동안 유효하게 만들 수 있습니다. 세션 방법을 기반으로 한 인증은 필연적으로 서버 (메모리 스토리지)에 약간의 압력을 가하며 (분산 세션을 처리해야 함), 크로스 사이트 요청 위조 공격 (CSRF)
1. 세션과 비교하여 서버에 저장할 필요가 없으며 서버 메모리 오버 헤드를 차지하지 않습니다.
2. 상태가없고 확장 가능 : 예를 들어, 서버 클러스터를 형성하기위한 3 개의 기계 (A, B, C)가 있습니다. 세션이 기계 A에 존재하는 경우 세션은 서버 중 하나에만 저장할 수 있습니다. 현재 세션이 B와 C에 저장되지 않았고 토큰을 사용하면 사용자 요청의 정당성을 확인할 수 있으므로 Machines B와 C에 액세스 할 수 없습니다. 몇 대를 더 추가해도 괜찮으므로 이것이 의미하는 바입니다.
3. 프론트 엔드 분리 및 교차 도메인 액세스 지원.
-JWT의 구성
{ "iss": "JWT Builder", "IAT": 1416797419, "exp": 1448333419, "aud": "www.battcn.com", "sub": "[email protected]", "givenname": "surname": "Levin", "이메일": "" "[email protected]", "역할": [ "admin", "member"]}JWT는 실제로 문자열이며 세 부분, 헤더, 페이로드 및 서명으로 구성됩니다 (위 그림에서 순서대로 정렬)
JWT 토큰 생성기 : https://jwt.io/
- 로그인 인증
- 인증 요청
잘못된 토큰
유효한 토큰
장점과 단점이 있습니다. 적용 가능한지 여부는 기술과 스타일보다는 명확하게 고려해야합니다.
TokenProperties Application.yml Resource가있는 키 매핑, 사용하기 쉬운 키 매핑
@configuration@configurationProperties (prefix = "battcn.security.token") public class tokenproperties { / *** {@link com.battcn.security.model.token.token} 토큰 연출 시간* / 개인 정관 Expirtime; / *** 발행자*/ 개인 문자열 발급자; /*** Signature 사용 된 키 {@link com.battcn.security.model.token.token}. */ 개인 문자열 사인 키; / *** {@link com.battcn.security.model.token.token} 새로 고발 시간*/ private integer refreshecpptime; // 세트를 얻는다 ...} 토큰에 의해 생성 된 클래스
@ComponentPublic 클래스 토큰 Factory {Private Final TokenProperties 속성; @autowired public tokenfactory (TokenProperties 속성) {this.properties = 속성; } / ** * jjwt를 사용하여 토큰을 생성합니다 * @param 컨텍스트 * @return * / public accesstoken createAccesstoken (userconText context) {옵션 .ofNullable (context.getUserName ()). OrelsetHrow (()-> new OrgalArgumentection ( "username없이 토큰을 만들 수 없음"); Optional.ofNullable (context.getAuthorities ()). OrelsetHrow (()-> 새로운 불법 행위 렉스크 ( "사용자가 권한이 없음")); 클레임 주장 = jwts.claims (). setSubject (context.getusername ()); CLEART.PUT ( "스코프", 컨텍스트 .getAuthorities (). stream (). map (Object :: Tostring) .collect (tolist ()); LocalDateTime currentTime = localDateTime.now (); String token = jwts.builder () .set -claims (cleshs) .setissuer (properties.getissuer ()) .setissueDat (date.from (current.atzone (ZoneId.SystemDefault ()) .SeTeXpiration (date.from.plusminutes (propertiets.geforation.prom.plusminutes)). .atzone (ZoneId.systemDefault ()). toInstant ())) .SignWith (signaturealgorithm.hs512, properties.getSigningKey ()) .compact (); New AccessToken (토큰, 클레임)을 반환합니다. } / ** * RefreshToken * @param usercontext * @return * / public token createrefreshtoken (usercontext usercontext) {if (stringUtils.isblank (usercontext.getusername ()))) {Throw New OppalarGumentection ( "username이 없으면 토큰을 만들 수 없음"); } localDateTime currentTime = localDateTime.now (); 클레임 주장 = jwts.claims (). setSubject (usercontext.getusername ()); CLEART.PUT ( "스코프", Arrays.AsList (Scopes.Refresh_Token.Authority ())); String token = jwts.builder () .set -claims (climes) .setissuer (properties.getissuer ()) .setid (uuid.randomuuid (). tostring ()) .setissuedat (date.from (currenttime.attime.systemdefault ()) .plusminutes (properties.getRefreshexptime ())) .atzone (ZoneId.SystemDefault ()). toInstant ()) .signwith (signaturealGorithm.hs512, properties.getSigningKey ()) .compact (); New AccessToken (토큰, 클레임)을 반환합니다. }} 토큰 만료 시간, 비밀 키를 포함한 구성 파일 자체로 확장 할 수 있습니다.
BATTCN : 보안 : 토큰 : 만료 시간 : 10 # 분 1440 새로 고침 -EXP- 시간 : 30 # 분 2880 발행자 : http://blog.battcn.com 사인-키 : battcn
WebSecurityConfig는 스프링 보안의 주요 구성입니다. 보안에서 필터를 정의하여 기본적으로 원하는 기능을 구현할 수 있습니다.
@configuration@enablewebsecuritypublic class websecurityconfig 확장 websecurityConfigurerAdapter {public static final String token_header_param = "x authorization"; 공개 정적 최종 문자열 form_based_login_entry_point = "/api/auth/login"; 공개 정적 최종 문자열 token_based_auth_entry_point = "/api/**"; public static final String manage_token_based_auth_entry_point = "/manage/**"; 공개 정적 최종 문자열 token_refresh_entry_point = "/api/auth/token"; @autowired Private RestAuthenticationEntryPoint AuthenticationEntryPoint; @autowired Private AuthenticationSuccessHandler SuccessHandler; @autowired Private AuthenticationFailureHandler 실패 핸들러; @autowired private loginauthenticationprovider loginauthenticationprovider; @autowired Private TokenauthenticationProvider TokenauthenticationProvider; @autowired Private Tokenextractor Tokenextractor; @autowired Private AuthenticationManager AuthenticationManager; 보호 된 로그 프로세싱 필터 BuildLoginProcessingFilter ()는 예외를 {loginProcessingFilter 필터 = 새 LoginProcessingFilter (form_based_login_entry_point, successHandler, failuchAndler); filter.setauthenticationManager (this.authenticationManager); 반환 필터; } Protected TokenauthenticationProcessingFilter BuildTokenAuthenticationProcessingFilter ()는 예외 {list <string> list = lists.newArrayList (token_based_auth_entry_point, manage_based_auth_entry_point); skippathRequestMatcher matcher = 새로운 skippathRequestMatcher (list); TokenauthenticationProcessingFilter 필터 = 새로운 TokenauthenticationProcessingFilter (실패 핸들러, TokenExtractor, Matcher); filter.setauthenticationManager (this.authenticationManager); 반환 필터; } @bean @bean public authenticationManager authenticationManagerBean ()은 예외 {return super.authenticationManagerBean (); } @override protected void configure (AuthenticationManagerBuilder Auth) {auth.authenticationProvider (loginauthenticationProvider); Auth.authenticationProvider (TokenauthenticationProvider); } @override protected void configure (httpsecurity http)는 예외를 {http .csrf (). disable () // jwt를 사용하고 있기 때문에 csrf를 꺼질 수 있습니다. .SessionCreationPolicy (SessionCreationPolicy.stationeless). (). () .AuthorizeRequests () .AntMatchers (form_based_login_entry_point) .permitall () // login end-point .antmatchers (token_refresh_entry_point) .permitall () // token reploint. (). .AntMatchers (TOKEN_BASED_AUTH_ENTRY_POINT) .Authenticated () // Protected API End-Points .AntMatchers (Manage_Token_Based_Auth_Entry_Point) .HasanYrole (ROLEENUM.ADMIN.NAME ()) usernamepasswordauthenticationfilter.class) .addfilterbefore (buildTokenAuthenticationProcessingFilter (), usernamepasswordauthenticationFilter.class); }}JWT 코드는 단순히 캡슐화되어 많은 컨텐츠를 포함하기 때문에 메인 조각 만 기사에 게시됩니다. 전체 코드가 필요한 경우 다음 git에서 직접 얻을 수 있습니다.
이 장의 코드 (battcn-jwt-service) : http://xiazai.vevb.com/201801/yuanma/battcn-cloud_jb51.rar
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.