本改编课程基于《OAuth 2.0 Cookbook_Protect Your Web Applications using Spring Security-Packt Publishing(2017)》。这本书侧重经过一个个精简的小例子来学习,如何使用spring security和oauth2.0来保护你的资源。java
课程从第二章开始,在Chaptor2,咱们将学习如下内容:web
本例将讲解如何配置客户端模式,当一个应用本身自己须要获取资源(无需用户受权),而不是获取资源全部者的资源时,客户端模式十分有用。redis
Java8 + mavenspring
本文源码可点击下载数据库
下面的步骤将指导你如何使用spring security OAuth2.0 配置一个受权中心和一个资源服务器:json
web
,security
依赖。pom.xml
,加入如下依赖:<dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> </dependency>
1.打开application.properties文件,输入:segmentfault
security.user.name=adolfosecurity.user.password=123api
2.尽管本例不关注于用户行为,咱们依然须要建立一个API来获取用户的profile。为了保证用户能够经过应用程序以一种安全的方式获取profile,新建UserProfile
和UserController
类,内容和《学习3》同样。安全
3.打开UserController
,将@RequestMapping
的注解由“/api/profile”
改成"/user"
。服务器
4.因为咱们在使用客户端模式,咱们将不容许客户端获取用户的profile。咱们能够建立一个API,来让客户端能够获取在本服务器注册的用户信息。可能这种模式对你而言没啥意义,如今咱们将目光移到如何使用客户端模式,而不是它对你有没有用。好了,咱们来建立AdminController
,一下是这个类的具体实现:
@Controller @RequestMapping("/api") public class AdminController { @RequestMapping("/users") public ResponseEntity<List<UserProfile>> getAllUsers() { return ResponseEntity.ok(getUsers()); } private List<UserProfile> getUsers() { List<UserProfile> users = new ArrayList<>(); users.add(new UserProfile("adolfo", "adolfo@mailinator.com")); users.add(new UserProfile("demigreite", "demigreite@mailinator.com")); users.add(new UserProfile("jujuba", "jujuba@mailinator.com")); return users; } }
4.为了保护这个API,咱们来建立一个资源服务配置类:
@Configuration @EnableResourceServer public class OAuth2ResourceServer extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests().anyRequest().authenticated() .and() .requestMatchers().antMatchers("/api/**"); } }
5.为了颁发access token,咱们须要建立一个受权中心,注意如今咱们定义了一个不一样的client ID和密码,还有不一样的authorizedGrantTypes:
@Configuration @EnableAuthorizationServer public class OAuth2AuthorizationServer extends AuthorizationServerConfigurerAdapter { @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("clientadmin") .secret("123") .authorizedGrantTypes("client_credentials") .scopes("admin"); } }
6.如今咱们要保护/users
API,也就是一批没有在客户端注册的用户信息:
@Configuration @EnableWebSecurity public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() .and() .antMatcher("/user/**").httpBasic() .and() .csrf().disable(); } }
如今所有配好了
本例展现了OAuth2.0一种特殊模式,让注册的客户端直接访问资源。以前的几种模式均是经过依赖用户的批准,第三方客户端才能访问资源。由于本例的特殊性,咱们专门新建了一个api,可让客户端拿到全部注册在OAuth2.0 Provider上的用户。
受权中心和资源服务中心的配置和前几种模式几乎一致,最大的不一样就是咱们不须要重定向地址,此外,咱们也要将验证模式改一下。就像这样的
clients.inMemory() .withClient("clientadmin") .secret("123") .authorizedGrantTypes("client_credentials") .accessTokenValiditySeconds(120) .scopes("admin");
如今咱们来启动服务,看看程序是如何与Oauth 2.0 Provider进行交互。当咱们使用客户端模式的时候,咱们并无任何用户的交互,因此也没有受权的模块。可是咱们仍是须要申请一个受权码:
咱们能够经过curl
curl -X POST " http://localhost:8080/oauth/t..." --user clientadmin:123 -d "grant_type=client_credentials&scope=admin"或者PostMan
发送请求后,你会获得以下的回复:
{ "access_token": "22924299-e715-4d7d-a30b-4d315aa932a3", "token_type": "bearer", "expires_in": 56, "scope": "admin" }
须要注意的是,使用客户端模式的时候,根据OAUTH2.0规范,不该该颁发refreshed token。由于使用客户端模式,不用考虑用户体检,客户端自身能够在access token过时的时候从新申请新的access token。
如今咱们能够携带access token去拿去资源了,可能你已经意识到,当咱们拿到access token后,咱们就能够获取资源,而无关咱们使用什么途径拿到这个资源的。
curl " http://localhost:8080/api/users" -H "Authorization: Bearer f6f81a52-7920-4f95-a83b-72fbfb5188c5"或者:
本例向你展现了如何使用客户端模式来保护资源,同时你还能够选择其余的模式(例如HTTP Basic Authentication)保护资源。咱们以前在第9步时,配置了WebSecurityConfiguration,其中
.antMatcher("/user/**").httpBasic()
说明匹配的endpoint将使用http 基础认证。所以,咱们没法经过以前的方法拿到/user
对应的资源,可是,咱们能够经过如下办法获取:
curl "<http://localhost:8080/user>" --user adolfo:123
或者:
客户端模式是客户端自己请求验证的行为,因此无需用户“认证”,不牵涉任何用户的行为。可是如今的微服务体系不怎么使用这种模式,由于这种模式能够轻易地经过refresh token来不断获取access token,而且也可使用动态的注册流程,在集成服务时自动执行全部流程。
考虑到不少微服务都是基于这种模式来沟通,所以存在大量的access token验证过程。基于这种状况,咱们须要考虑验证策略,不一样的策略会不一样程度地影响服务器的性能。在本周的最后章节,咱们将学到,如何建立负载测试应用程序,和如何使用Gatling测量验证访问令牌时的响应时间。