ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [OAuth2]
    Springboot/Security 2019. 12. 17. 15:57

    : 표준 인증 프로토콜. 토큰을 사용해 인증을 제공한다.

     

    # 승인타입

     

    - Authorization Code Grant Type : (권한부여코드승인) auth server에 access token을 받아 인증에 이용.

    - Implict Grant Type                 : (암시적 승인) access token을 즉시 반환해 인증에 이용. 응답타입 token

     

    # 순서

     

    1-1) client  -> auth server  : 권한부여코드 요청  {Client id /  Redirect URL / reponse_type(code | token)} 전달

    1-2) resource owner로그인 : 권한부여코드(code | token) Redirect URL로 client에게 전달

     

    2-1) client  -> auth server  : 권한부여코드를 반환, accessToken 요청{client id/secret/redirectUrl/grant_type} 전달

    2-2) access token 전달

     

    3-1) client  -> resource server  : accessToken 으로 API 호출

    3-2) 요청 데이터 전달

     


    [Login]

     

     

     

    package com.example;
    
    import java.security.Principal;
    import java.util.ArrayList;
    import java.util.LinkedHashMap;
    import java.util.List;
    import java.util.Map;
    
    import javax.servlet.Filter;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties;
    import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.context.properties.NestedConfigurationProperty;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.annotation.Order;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.oauth2.client.OAuth2ClientContext;
    import org.springframework.security.oauth2.client.OAuth2RestTemplate;
    import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter;
    import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter;
    import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
    import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
    import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
    import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
    import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
    import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
    import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
    import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.filter.CompositeFilter;
    
    @SpringBootApplication
    @RestController
    @EnableOAuth2Client
    @EnableAuthorizationServer
    @Order(200)
    public class SocialApplication extends WebSecurityConfigurerAdapter {
    
    	@Autowired
    	OAuth2ClientContext oauth2ClientContext;
    
    	@RequestMapping({ "/user", "/me" })
    	public Map<String, String> user(Principal principal) {
    		Map<String, String> map = new LinkedHashMap<>();
    		map.put("name", principal.getName());
    		return map;
    	}
    	
    	@Override
    	protected void configure(HttpSecurity http) throws Exception {
    		System.out.println("configure 실행합니다");
    		http.antMatcher("/**")																// 모든요청은 보호됩니다
    				.authorizeRequests()
    					.antMatchers("/", "/login**", "/webjars/**").permitAll()				// 홈페이지,로긴 앤드포인트는 예외
    					.anyRequest().authenticated()											// 그외 요청은 인증사용자가 필요합니다
    				.and().exceptionHandling()													
    					.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/"))	// 인증안된 사용자는 홈페이지로 리디렉션
    				.and().logout().logoutSuccessUrl("/").permitAll()
    				.and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
    				.and().addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
    		;
    	}
    	
    	@Configuration
    	@EnableResourceServer
    	protected static class ResourceServerConfiguration
    	    extends ResourceServerConfigurerAdapter {
    	  @Override
    	  public void configure(HttpSecurity http) throws Exception {
    		  
    		  System.out.println("ResourceServerConfigurer 실행합니다");
    		  
    	    http
    	      .antMatcher("/me")
    	      .authorizeRequests().anyRequest().authenticated();
    	  }
    	}
    
    	
    	private Filter ssoFilter() {
    		System.out.println("ssofilter 실행합니다");
    		
    		CompositeFilter filter = new CompositeFilter();
    		List<Filter> filters = new ArrayList<>();
    		filters.add(ssoFilter(facebook(), "/login/facebook"));
    		filters.add(ssoFilter(github(), "/login/github"));
    		filter.setFilters(filters);
    		return filter;
    	}
    
    	private Filter ssoFilter(ClientResources client, String path) {
    		  OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(path);
    		  OAuth2RestTemplate template = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
    		  filter.setRestTemplate(template);
    		  UserInfoTokenServices tokenServices = new UserInfoTokenServices(
    		      client.getResource().getUserInfoUri(), client.getClient().getClientId());
    		  tokenServices.setRestTemplate(template);
    		  filter.setTokenServices(tokenServices);
    		  return filter;
    	}
    	
    	@Bean
    	public FilterRegistrationBean<OAuth2ClientContextFilter> oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
    		System.out.println("security filter 실행합니다");
    		
    		FilterRegistrationBean<OAuth2ClientContextFilter> registration = new FilterRegistrationBean<OAuth2ClientContextFilter>();
    		registration.setFilter(filter);
    		registration.setOrder(-100);
    		return registration;
    	}
    	
    	@Bean
    	@ConfigurationProperties("github")
    	public ClientResources github() {
    	  return new ClientResources();
    	}
    
    	@Bean
    	@ConfigurationProperties("facebook")
    	public ClientResources facebook() {
    	  return new ClientResources();
    	}
    	
    	public static void main(String[] args) {
    		SpringApplication.run(SocialApplication.class, args);
    	}
    
    }
    
    class ClientResources {
    	
    	  @NestedConfigurationProperty
    	  private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();
    
    	  @NestedConfigurationProperty
    	  private ResourceServerProperties resource = new ResourceServerProperties();
    
    	  public AuthorizationCodeResourceDetails getClient() {
    	    return client;
    	  }
    
    	  public ResourceServerProperties getResource() {
    	    return resource;
    	  }
    
    }

     

    이걸.. 분리해보자!

     

    'Springboot > Security' 카테고리의 다른 글

    [Security] OAuth2 debug  (0) 2020.06.15
    [Spring Security]  (0) 2020.01.18
Designed by Tistory.