Spring boot 開發指南第七節 搭建密碼受權服務器

在這裏咱們使用Spring boot中的 secruity 和 Oauth2.0 搭建一個受權服務器 java

讓其餘應用或者服務使用用戶名和密碼 POST到這個服務器 來換取access_token spring

這種場景在實際應用中仍是很常見的api

1. 爲了防止明文的密碼被劫持 首先在服務器端開啓SSL

具體方法請訪問 https://my.oschina.net/u/659068/blog/1549186服務器

2. 而後在POM開始引用依賴 主要內容是Spring security 和 Oauth2.0 插件

<!-- security -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
		
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-test</artifactId>
			<scope>test</scope>
		</dependency>
		
		<dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
        </dependency>
		
		<!-- security oauth2 -->
		<dependency>
	        <groupId>org.springframework.cloud</groupId>
	        <artifactId>spring-cloud-starter-oauth2</artifactId>
		</dependency>

3.SpringSecurity的主配置文件

這裏主要就是設置了訪問密碼 路徑配置等 其中 AuthenticationManager  是必須的app

@Configuration
@EnableWebSecurity
@Order(2)
public class SecurityConfig extends WebSecurityConfigurerAdapter {  
	

	@Autowired
    private ClientDetailsService clientDetailsService;

	@Configuration
    protected static class AuthenticationConfiguration extends
            GlobalAuthenticationConfigurerAdapter {

        @Override
        public void init(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication().withUser("user").password("zzz123")
                    .roles("USER").and().withUser("admin").password("zzz123")
                    .roles("USER", "ADMIN");
        }

    }    

    @Override  
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {  
        auth.inMemoryAuthentication().withUser("shili").password("zzz123").roles("ADMIN");  
    }  
      
  
    @Override  
    protected void configure(HttpSecurity http) throws Exception {  
  	
    	http.csrf().disable()
		.anonymous().disable()
	  	.authorizeRequests()
	  	.antMatchers("/oauth/token").permitAll()
	  	.and().exceptionHandling().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/"));
    	
    	
    }
    
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    
    @Bean
    public TokenStore tokenStore() {
        return new InMemoryTokenStore();
    }
 
    @Bean
    @Autowired
    public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){
        TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
        handler.setTokenStore(tokenStore);
        handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
        handler.setClientDetailsService(clientDetailsService);
        return handler;
    }
     
    @Bean
    @Autowired
    public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
        TokenApprovalStore store = new TokenApprovalStore();
        store.setTokenStore(tokenStore);
        return store;
    }
}

4. Oauth 2.0 的配置以下 

其中 allowFormAuthenticationForClients 是必須的 這裏的 client_id 和 secret 也能夠按照需求註冊受權less

這裏是寫死的 這裏之後會修改curl

@Configuration
@EnableAuthorizationServer
public class SecurityOauth2Config extends AuthorizationServerConfigurerAdapter {
	
	private static String REALM="MY_OAUTH_REALM";
	
	
	@Autowired
    private TokenStore tokenStore;
 
    @Autowired
    private UserApprovalHandler userApprovalHandler;
 	
	@Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;
		
	@Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

		clients.inMemory()
        .withClient("13890999")
        .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
        .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
        .scopes("read", "write", "trust")
        .secret("secret")
        .accessTokenValiditySeconds(120).//Access token is only valid for 2 minutes.
        refreshTokenValiditySeconds(600);//Refresh token is only valid for 10 minutes.

	}
	
    @Override  
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {  
        //enable client to get the authenticated when using the /oauth/token to get a access token  
        //there is a 401 authentication is required if it doesn't allow form authentication for clients when access /oauth/token  
        oauthServer.allowFormAuthenticationForClients().realm(REALM+"/client");
    }  

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler)
                .authenticationManager(authenticationManager);
    }
 
	
}

5. 設置下資源服務器的配置 

@Configuration
@EnableResourceServer
@Order(6)
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
	
	private static final String RESOURCE_ID = "my_rest_api";
	
	@Override
	public void configure(ResourceServerSecurityConfigurer resources) {
		resources.resourceId(RESOURCE_ID).stateless(false);
	}

	@Override
	public void configure(HttpSecurity http) throws Exception {
		http.
		anonymous().disable()
		.requestMatchers().antMatchers("/sayhello")
		.and().authorizeRequests()
		.antMatchers("/sayhello").access("hasRole('ADMIN')")
		.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());		 
	}
}

6. 測試方法

curl https://localhost:8080/oauth/token -k -d client_id=13890999 -d client_secret=secret -d grant_type=password -d username=shili -d password=zzz123

參數增長-k 跳過了證書的驗證 不然就會出現錯誤提示 證書鏈是由不受信任的頒發機構頒發的。ide

看到以下信息 表示獲取ACCESS_token 成功了! spring-boot

{"access_token":"66e5ab1d-427f-4801-a3c5-b47d3a96fbad","token_type":"bearer","re
fresh_token":"cc9ef96f-d771-4ec9-a4fc-9064809886e3","expires_in":119,"scope":"re
ad write trust"}
相關文章
相關標籤/搜索