OAuth 2.0
是一种工业级的受权协议。OAuth 2.0是从建立于2006年的OAuth 1.0继承而来的。OAuth 2.0致力于帮助开发者简化受权并为web应用、桌面应用、移动应用、嵌入式应用提供具体的受权流程。java
OAuth 2.0 is the industry-standard protocol for authorization. OAuth 2.0 supersedes the work done on the original OAuth protocol created in 2006. OAuth 2.0 focuses on client developer simplicity while providing specific authorization flows for web applications, desktop applications, mobile phones, and living room devices.git
为了方便理解,以经常使用的使用微信登陆
为例github
Resource Ownerweb
资源拥有者,对应微信的每一个用户微信上设置的我的信息是属于每一个用户的,不属于腾讯。spring
Resource Serverapi
资源服务器,通常就是用户数据的一些操做(增删改查)的REST API,好比微信的获取用户基本信息的接口。安全
Client Application服务器
第三方客户端,对比微信中就是各类微信公众号开发的应用,第三方应用通过认证服务器
受权后便可访问资源服务器
的REST API来获取用户的头像、性别、地区等基本信息。微信
Authorization Servercookie
认证服务器,验证第三方客户端是否合法。若是合法就给客户端颁布token,第三方经过token来调用资源服务器的API。
anthorization_code
受权码类型,适用于Web Server Application。模式为:客户端先调用/oauth/authorize/
进到用户受权界面,用户受权后返回code
,客户端而后根据code和appSecret
获取access token
。
implicit 简化类型,相对于受权码类型少了受权码获取的步骤。客户端应用受权后认证服务器会直接将access token放在客户端的url。客户端解析url获取token。这种方式实际上是不太安全的,能够经过https安全通道和缩短access token的有效时间来较少风险。
password
密码类型,客户端应用经过用户的username和password获access token。适用于资源服务器、认证服务器与客户端具备彻底的信任关系,由于要将用户要将用户的用户名密码直接发送给客户端应用,客户端应用经过用户发送过来的用户名密码获取token,而后访问资源服务器资源。好比支付宝就能够直接用淘宝用户名和密码登陆,由于它们属于同一家公司,彼此充分信任。
client_credentials
客户端类型,是不须要用户参与的一种方式,用于不一样服务之间的对接。好比本身开发的应用程序要调用短信验证码服务商的服务,调用地图服务商的服务、调用手机消息推送服务商的服务。当须要调用服务是能够直接使用服务商给的appID
和appSecret
来获取token,获得token以后就能够直接调用服务。
有的时候资源服务器和认证服务器是两个不一样的应用,有的时候资源服务器和认证服务器在通一个应用中,不一样之处在于资源服务器是否须要检查token的有效性,前者须要检查,后者不须要。这里实现后者。
@Configuration public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.formLogin() .and().csrf().disable() .authorizeRequests().anyRequest().authenticated(); } @Override public void configure(WebSecurity web) throws Exception { super.configure(web); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("lyt").password("lyt").authorities("ROLE_USER") .and().withUser("admin").password("admin").authorities("ROLE_ADMIN"); } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } }
@EnableAuthorizationServer @Configuration public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory().withClient("client") .scopes("read","write") .secret("secret") .authorizedGrantTypes("authorization_code","password","implicit","client_credentials");} @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { super.configure(security); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager); } @Autowired @Qualifier("authenticationManagerBean") private AuthenticationManager authenticationManager; }
@EnableGlobalMethodSecurity(prePostEnabled = true) @EnableResourceServer @Configuration public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.antMatcher("/oauth2/api/**").authorizeRequests() .antMatchers(HttpMethod.GET, "/read/**").access("#oauth2.hasScope('read')") .antMatchers(HttpMethod.POST, "/write/**").access("#oauth2.hasScope('write')") .antMatchers(HttpMethod.PUT, "/write/**").access("#oauth2.hasScope('write')") .antMatchers(HttpMethod.DELETE, "/write/**").access("#oauth2.hasScope('write')"); } }
filter-order
设置须要在application.yml
中将filter-order设置成3,具体缘由参考 连接
为了不认证服务器的cookie和客户端的cookie冲突,出现错误,最好修改cookie name
或者设置contextPath
。
postman
中提供OAuth 2.0的认证方式,能够获取到token以后再把认证加入http请求中,便可请求资源服务器的REST API
测试代码github地址。有兴趣能够关注微信公众帐号获取最新推送文章。