本文共 6869 字,大约阅读时间需要 22 分钟。
OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。OAuth2.0是OAuth协议的延续版本,但不向后兼容OAuth 1.0即完全废止了OAuth1.0。
在APP或者网页接入一些第三方应用时,时长会需要用户登录另一个合作平台,比如QQ,微博,微信的授权登录。OAuth 提供三种角色,分别是:
认证流程如下:
本实例包含三个服务,服务注册中心(server-service),客户端(client-service),以及授权服务(oauth-service),客户端和授权服务向注册中心注册,授权服务负责授权给客户端,之后客户端能访问相关的资源。
Spring OAuth2 分为两部分,分别是:
OAuth2 Provider 负责公开被OAuth保护起来的资源,需要配置代表用户的OAuth 客户端信息,被允许的用户就可以访问被oauth保护的资源,OAuth2 Provider需要提供认证的API接口,用户通过账号密码来获取权限去访问被OAuth保护的资源,OAuth2 Provider 又可分为两部分:
他们通常不在一个服务中,一个授权服务可以对应多个资源服务,资源服务也可以是授权服务。
Authorization Server(授权服务) 配置
//授权服务 @Configuration @EnableAuthorizationServer protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { //@Autowired //@Qualifier("dataSource") private DataSource dataSource; //配置将Token存储到内存 private TokenStore tokenStore = new InMemoryTokenStore(); //配置将Token存储到数据库 //JdbcTokenStore tokenStore=new JdbcTokenStore(dataSource); //配置开启密码类型的验证,只有配置了才会开启 @Autowired @Qualifier("authenticationManagerBean") private AuthenticationManager authenticationManager; @Autowired private UserService userServiceDetail; //配置客户端的基本信息 @Override //配置客户端信息 public void configure(ClientDetailsServiceConfigurer clients) throws Exception { String finalSecret = new BCryptPasswordEncoder().encode("123456"); clients.inMemory() //客户端Id,在Authorization Server 是唯一的 .withClient("client-service") //认证类型 //客户端模式 .authorizedGrantTypes("client_credentials", "password","refresh_token") //权限范围 .scopes("server") //权限信息 .authorities("oauth2") //客户端密码 .secret(finalSecret) //密码模式 .and().withClient("client_2") .authorizedGrantTypes("password", "refresh_token") .scopes("server") .authorities("oauth2") .secret(finalSecret) .accessTokenValiditySeconds(2*3600);//2小时过期 } @Override //配置Token节点的安全策略 public void configure(AuthorizationServerEndpointsConfigurer endpoints) { endpoints .tokenStore(tokenStore)//Token的存储方式 //.tokenStore(new RedisTokenStore(redisConnectionFactory)) .authenticationManager(authenticationManager)//开启密码类型的验证 .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST) //配置读取用户验证信息,获取用户认证信息的接口 .userDetailsService(userServiceDetail); //endpoints.reuseRefreshTokens(true); } @Override //配置授权Token的节点和Token服务 public void configure(AuthorizationServerSecurityConfigurer oauthServer) { //配置获取Token的策略,允许表单认证,配置之后可通过表单获取Token oauthServer.allowFormAuthenticationForClients(); } }
Spring Security 认证配置
@Configuration@EnableWebSecurity//开启WebSecurity功能@EnableGlobalMethodSecurity(prePostEnabled = true)//开启方法上的保护public class SecurityConfig extends WebSecurityConfigurerAdapter { @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity http) throws Exception { http.requestMatchers() .anyRequest() .and().authorizeRequests() //.antMatchers("/admin/**").authenticated() .antMatchers("/css/**", "/test","/oauth/**").permitAll() .antMatchers("/admin/**").hasRole("ADMIN")///admin/**的URL都需要有超级管理员角色,如果使用.hasAuthority()方法来配置,需要在参数中加上ROLE_,如下.hasAuthority("ROLE_超级管理员") .anyRequest().authenticated();//其他的路径都是登录后即可访问 } //配置验证管理的Bean @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); }}
Resources Server(资源服务) 配置
//配置资源服务 //@Configuration //@EnableResourceServer protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { //资源访问控制,可配置必须通过token认证过后才可以访问的资源,permitAll()表示不需要token可直接访问 http .authorizeRequests() .antMatchers("/login").permitAll(); } }
客户端用来访问被 OAuth保护起来的资源,需要配置
security: oauth2: resource: user-info-uri: http://localhost:8763/current client: # 客户端Id ,与OAuth Provider 中的配置一一对应 clientId: client-service # 客户端密码,与OAuth Provider 中的配置一一对应 clientSecret: 123456 # 获取Token的节点 accessTokenUri: http://localhost:8763/oauth/token grant-type: client_credentials,password # 客户端的域 scope: server
@EnableOAuth2Client@EnableConfigurationProperties@Configurationpublic class OAuth2ClientConfig { //配置受保护的资源信息 @Bean @ConfigurationProperties(prefix = "security.oauth2.client") public ClientCredentialsResourceDetails clientCredentialsResourceDetails() { return new ClientCredentialsResourceDetails(); } //配置过滤器,存储当前请求和上下文 /*@Bean public RequestInterceptor oauth2FeignRequestInterceptor(){ return new OAuth2FeignRequestInterceptor(new DefaultOAuth2ClientContext(), clientCredentialsResourceDetails()); }*/ @Bean public OAuth2RestTemplate clientCredentialsRestTemplate() { return new OAuth2RestTemplate(clientCredentialsResourceDetails()); }}
也可以仅使用 @EnableOAuth2Client 简化配置。
在客户端开启资源服务,Spring Security 提供了认证过滤器,可对URL进行开放和拦截。
@Configuration@EnableResourceServer//开启资源服务@EnableGlobalMethodSecurity(prePostEnabled = true)public class ResourceServerConfigurer extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/student").permitAll(); }}
配置完成后,我们可以通过 postMan 或者在浏览器上访问以下链接获取 Token
http://localhost:8763/oauth/token?username=123&password=123&grant_type=password&scope=server&client_id=client-service&client_secret=123456
携带 Token 即可访问受保护的资源
http://localhost:8762/hi?access_token=7e664c6b-b60f-4f1a-97c2-9dea092044c4
公众号:【星尘Pro】
github:
推荐阅读
参考<<深入理解Spring Cloud 与微服务构建>>
转载地址:http://pdfsi.baihongyu.com/