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"}
相关文章
相关标签/搜索