完整項目代碼:https://git.oschina.net/wang-bata/springboot-oauth2-server.gitjava
項目配置:java jdk1.8, springboot, springsecurity,springoauth2, 利用springOauth2.0來實現 oauth2.0協議 配置方式有xml和javaconfig 本文利用javaconfig 因爲項目是用jar包方式啓動因此頁面顯示用了 thmyleaf框架。git
1:資源服務器:web
資源服務器是指託管資源的服務器。好比,Facebook或Google就是資源服務器(或者有一個資源服務器)。spring
以下例子:sql
A公司處理是一個雲存儲公司,擁有用戶的博客,文章,說說,動態等資源,此時這些數據應該被視爲資源,但資源不單單是這些數據,還能夠包括用戶的 我的信息,不過這些信息比較敏感!跨域
資源服務器有2種配置方式,springboot
- 一個資源服務器對應一個資源ID (若是資源比較大,比較密集)
- 一個資源服務器對應多個資源ID (有時候一個資源服務比較小對系統消耗小,能夠在一臺服務器配置多個資源服務器 這樣有利於公司資源的合理分配)
//一個資源服務器對應一個資源ID (若是資源比較大,比較密集) package com.wang.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; import org.springframework.security.web.header.HeaderWriter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.sql.DataSource; @Configuration @EnableResourceServer public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { @Autowired private DataSource dataSource; @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { TokenStore tokenStore = new JdbcTokenStore(dataSource); resources.resourceId("user-services").tokenStore(tokenStore).stateless(true); } @Override public void configure(HttpSecurity http) throws Exception { http .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.NEVER) .and() .requestMatchers().antMatchers("/bata/**") .and() // For some reason we cant just "permitAll" OPTIONS requests which are needed for CORS support. Spring Security // will respond with an HTTP 401 nonetheless. // So we just put all other requests types under OAuth control and exclude OPTIONS. .authorizeRequests() .antMatchers(HttpMethod.GET, "/bata/**").access("#oauth2.hasScope('read')") .antMatchers(HttpMethod.POST, "/bata/**").access("#oauth2.hasScope('write')") .antMatchers(HttpMethod.PATCH, "/bata/**").access("#oauth2.hasScope('write')") .antMatchers(HttpMethod.PUT, "/bata/**").access("#oauth2.hasScope('write')") .antMatchers(HttpMethod.DELETE, "/bata/**").access("#oauth2.hasScope('write')") .and() // Add headers required for CORS requests. .headers().addHeaderWriter(new HeaderWriter() { @Override public void writeHeaders(HttpServletRequest request, HttpServletResponse response) { response.addHeader("Access-Control-Allow-Origin", "*"); if (request.getMethod().equals("OPTIONS")) { response.setHeader("Access-Control-Allow-Methods", request.getHeader("Access-Control-Request-Method")); response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers")); } } }); } }
//一個資源服務器對應多個資源的配置 package com.wang.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfiguration; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; import org.springframework.security.web.header.HeaderWriter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.sql.DataSource; import java.util.Arrays; import java.util.List; @Configuration public class ResourceServerConfig { @Autowired private DataSource dataSource; //配置jdbc數據源 @Bean protected ResourceServerConfiguration BataResources() { ResourceServerConfiguration resource = new ResourceServerConfiguration() { // Switch off the Spring Boot @Autowired configurers public void setConfigurers(List<ResourceServerConfigurer> configurers) { super.setConfigurers(configurers); } }; resource.setConfigurers(Arrays.<ResourceServerConfigurer>asList(new ResourceServerConfigurerAdapter() { @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { TokenStore tokenStore = new JdbcTokenStore(dataSource); resources.resourceId("bata-services").tokenStore(tokenStore).stateless(true); //設置資源ID } @Override public void configure(HttpSecurity http) throws Exception { http .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.NEVER) .and() .requestMatchers().antMatchers("/bata/**") //添加要進行資源隔離的路經 .and() .authorizeRequests() .antMatchers(HttpMethod.GET, "/bata/**").access("#oauth2.hasScope('read')") .antMatchers(HttpMethod.POST, "/bata/**").access("#oauth2.hasScope('write')") .antMatchers(HttpMethod.PATCH, "/bata/**").access("#oauth2.hasScope('write')") .antMatchers(HttpMethod.PUT, "/bata/**").access("#oauth2.hasScope('write')") .antMatchers(HttpMethod.DELETE, "/bata/**").access("#oauth2.hasScope('write')") .and() .headers().addHeaderWriter(new HeaderWriter() { @Override public void writeHeaders(HttpServletRequest request, HttpServletResponse response) { response.addHeader("Access-Control-Allow-Origin", "*"); //配置跨域訪問 if (request.getMethod().equals("OPTIONS")) { response.setHeader("Access-Control-Allow-Methods", request.getHeader("Access-Control-Request-Method")); response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers")); } } }); } })); resource.setOrder(3); return resource; } @Bean protected ResourceServerConfiguration UserResources() { ResourceServerConfiguration resource = new ResourceServerConfiguration() { // Switch off the Spring Boot @Autowired configurers public void setConfigurers(List<ResourceServerConfigurer> configurers) { super.setConfigurers(configurers); } }; resource.setConfigurers(Arrays.<ResourceServerConfigurer>asList(new ResourceServerConfigurerAdapter() { @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { TokenStore tokenStore = new JdbcTokenStore(dataSource); resources.resourceId("user-services").tokenStore(tokenStore).stateless(true); } @Override public void configure(HttpSecurity http) throws Exception { http .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.NEVER) .and() .requestMatchers().antMatchers("/user/**") .and() .authorizeRequests() .antMatchers(HttpMethod.GET, "/user/**").access("#oauth2.hasScope('read')") .antMatchers(HttpMethod.POST, "/user/**").access("#oauth2.hasScope('write')") .antMatchers(HttpMethod.PATCH, "/user/**").access("#oauth2.hasScope('write')") .antMatchers(HttpMethod.PUT, "/user/**").access("#oauth2.hasScope('write')") .antMatchers(HttpMethod.DELETE, "/user/**").access("#oauth2.hasScope('write')") .and() .headers().addHeaderWriter(new HeaderWriter() { @Override public void writeHeaders(HttpServletRequest request, HttpServletResponse response) { response.addHeader("Access-Control-Allow-Origin", "*"); if (request.getMethod().equals("OPTIONS")) { response.setHeader("Access-Control-Allow-Methods", request.getHeader("Access-Control-Request-Method")); response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers")); } } }); } })); resource.setOrder(4); return resource; } }