[Spring Boot] Oauth2.0 jwt token 구현
[Spring Boot] Oauth2.0 jwt token 구현
Repository
mooogi 2020. 1. 3. 03:05
resoucre 서버와 authorization 서버를 함께 구성하였음
주요 Dependencies
- lombok
- spring-boot-starter-security
- spring-security-oauth2
- spring-boot-starter-data-jpa
- spring-boot-starter-web
- mysql
프로젝트 구조
OauthApplication - 기본 springboot application
AuthorizationServiceConfigurerAdapterImpl - Authorizaion Server 구현
ResourceServerConfigurerAdapterImpl - Resourcet Server 구현
Member - 서비스할 객체
UserRepository - api service
Application 설정들
application.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #MYSQL spring: datasource: url: jdbc:mysql: / / localhost: 3306 / study_db?autoReconnect = true & useSSL = false driverClassName: com.mysql.jdbc.Driver username: root password: 1234 jpa: show - sql: true #security 설정 security: user: name: user password: test oauth2: resource: jwt: key - uri: http: / / localhost: 9093 / oauth / token_key client: client - id: foo client - secret: bar authorization: token - key - access: isAuthenticated() #로깅레벨 logging: level: ROOT: error #포트 server: port: 9093 http://colorscripter.com/info#e " target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
mysql 지정, spring security에서 client와 resoucre-owner정보 설정,
oauth의 토큰을 요청하는 url을 지정해주고(oauth/token_key는 기본값이다)
jwt 생성에 사용하는 키는 설정하지 않아 현재 자동으로 생성된다
API 구현
Member.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Entity @Getter @Setter @NoArgsConstructor(access = AccessLevel.PRIVATE) public class Member { @Id @GeneratedValue private Long id; private String name; private String username; private String remark; @Builder public Member( String name, String username, String remark) { this .name = name; this .username = username; this .remark = remark; } } http://colorscripter.com/info#e " target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
jpa 형식으로 id, name, username, remark 필드를 갖는 Member 도메인 생성
@Id는 해당 프로퍼티가 테이블의 primary key 역할을 한다는것을 지정
@GeneratedVlaue는 id값을 DB의 identity 컬럼, 시퀀스, 테이블등을 이용하여 자동으로 생성해주도록 지정한다.
인자가없는 생성자를 private로 선언
MemberRepository.java
1 2 3 4 @RepositoryRestResource public interface MemberRepository extends PagingAndSortingRepository < Member, Long > {} http://colorscripter.com/info#e " target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
dependency에서 선언한 spring-data-rest에서 제공하는 기능으로
@RepositoryRestResource 어노테이션을 위와같은 방법으로 사용하는것 만으로
내부적으로 Rest API를 만들어 준다(여러종류의 요청을 생성)
여기까지의 구현만으로
localhost:{port}/members (전체 member조회)
localhost:{port}/members/2 (id가 2인 member조회)
등의 요청을 받아 응답할 수 있는 api서버가 만들어진다
ResourceServer 설정 ResourceServerConfigurerAdapterImpl.java 1 2 3 4 5 6 7 8 9 10 11 12 @EnableResourceServer // 자원서버 설정 @Configuration public class ResourceServerConfigurerAdapterImpl extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers( "/members" , "/members/**" ).access( "#oauth2.hasScope('read')" ) .anyRequest().authenticated(); } } http://colorscripter.com/info#e " target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter ResourceServerConfigurerAdapter를 상속받아 configure를 override하여 자원서버에대한 설정을 수행
localhost:{port}/members와 이후 url 요청시 권한을 가져야 가능하도록 하고(token이 있고, 해당 스코프를 가져야함)
AuthorizationServer 설정 AuthorizationServiceConfigurerAdapterImpl.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 @EnableAuthorizationServer @Configuration public class AuthorizationServiceConfigurerAdapterImpl extends OAuth2AuthorizationServerConfiguration{ private final JwtAccessTokenConverter jwtAccessTokenConverter; public AuthorizationServiceConfigurerAdapterImpl(BaseClientDetails details, AuthenticationManager authenticationManager, ObjectProvider < TokenStore > tokenStore, ObjectProvider < AccessTokenConverter > tokenConverter, AuthorizationServerProperties properties) { super (details, authenticationManager, tokenStore, tokenConverter, properties); this .jwtAccessTokenConverter = new JwtAccessTokenConverter(); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { super .configure(endpoints); endpoints.accessTokenConverter(jwtAccessTokenConverter); } } @Configuration class OAuth2Configuration { @Bean public TokenStore tokenStore() { return new JwtTokenStore(jwtAccessTokenConverter()); } @Bean public JwtAccessTokenConverter jwtAccessTokenConverter() { return new JwtAccessTokenConverter(); } } http://colorscripter.com/info#e " target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white"> cs
OAuth2AuthorizationServerConfiguration를 상속받아 AuthorizionServer를 구현한다
상속시 AuthorizationServiceConfigurerAdapterImpl 메소드를 구현해야 하는데 기본설정에
jwtAccessTokenConverter만 추가로 지정하였다
Oauth2Configuration에서는 토큰을 jwt로 사용하기위해
configuration을 추가하여 tokenstore와 Converter bean을 만들어줬다
테스트 1. api를 통해 조회할 자료 생성
지정해준 mysql에 member테이블을 만들고 조회할 값들을 미리 넣어준다(@Entity로 선언된 Member Class와연동)
2. access token 없이 조회
token이 없을시 MemberRepository를 이용해 구현한 api에 조회할 수 없다
3. access token 발급 후 조회
application.yml에 설정해둔 client_id, security의 기본 user, password등의 값을 이용해 토큰을 발급받는다
권한설정부분과 body에 필요한 파라미터를 설정후 /oauth/token url에 post로 요청하여 토큰을 발급받는다
발급받은 토큰을 확인해보자
jwt.io 사이트를 이용해 토큰을 Decode하여 확인 결과 정상적으로 발급되었음을 알수있다
발급된토큰을 포함하여 /members를 다시 요청해보면
정상적으로 조회하려던 api의 리턴을 받을 수 있다
해당프로젝트 소스 : https://github.com/m0oogi/oauth2_msa
from http://mpository.tistory.com/5 by ccl(A) rewrite - 2020-03-06 18:21:17
댓글
댓글 쓰기