目录
一、oauth2
OAuth: OAuth(开放授权)是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容。
QQ登录OAuth2.0:对于用户相关的OpenAPI(例如获取用户信息,动态同步,照片,日志,分享等),为了保护用户数据的安全和隐私,第三方网站访问用户数据前都需要显式的向用户征求授权。
QQ登录OAuth2.0采用OAuth2.0标准协议来进行用户身份验证和获取用户授权,相对于之前的OAuth1.0协议,其认证流程更简单和安全。
地址:https://wiki.connect.qq.com
二、OAuth认证和授权的过程
OAuth认证和授权的过程如下:
1、用户访问第三方网站网站,想对用户存放在服务商的某些资源进行操作。
2、第三方网站向服务商请求一个临时令牌。
3、服务商验证第三方网站的身份后,授予一个临时令牌。
4、第三方网站获得临时令牌后,将用户导向至服务商的授权页面请求用户授权,然后这个过程中将临时令牌和第三方网站的返回地址发送给服务商。
5、用户在服务商的授权页面上输入自己的用户名和密码,授权第三方网站访问所相应的资源。
6、授权成功后,服务商将用户导向第三方网站的返回地址。
7、第三方网站根据临时令牌从服务商那里获取访问令牌。
8、服务商根据令牌和用户的授权情况授予第三方网站访问令牌。
9、第三方网站使用获取到的访问令牌访问存放在服务商的对应的用户资源。
流程总结:
1、 生成授权链接,获取授权码
2、 使用授权码获取AccessToken
3、 使用AccessToken获取openId
4、 使用openId获取用户信息
三、OAuth2为我们提供了四种授权方式
1、授权码模式(authorization code)用在客户端与服务端应用之间授权
2、简化模式(implicit)用在移动app或者web app(这些app是在用户的设备上的,如
在手机上调起微信来进行认证授权)
3、密码模式(resource owner password credentials)应用直接都是受信任的(都是由一家公司开发的)
4、客户端模式(client credentials)用在应用API访问
四、OAuth2环境搭建OAuth2环境搭建
oauth2-server:OAUTH2认证授权中心服务
order_service: 普通微服务,验证授权服务
1、认证授权中心服务
1)、密码模式
Maven依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<!-- 管理依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.M7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- springboot整合freemarker -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-->spring-boot 整合security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- spring-cloud-starter-oauth2 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
</dependencies>
<!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
创建配置信息
// 配置授权中心信息
@Configuration
@EnableAuthorizationServer // 开启认证授权中心
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
// accessToken有效期
private int accessTokenValiditySeconds = 7200; // 两小时
// 添加商户信息
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// withClient appid
clients.inMemory().withClient("client_1").secret(passwordEncoder().encode("123456"))
.authorizedGrantTypes("password","client_credentials","refresh_token").scopes("all").accessTokenValiditySeconds(accessTokenValiditySeconds);
}
// 设置token类型
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.authenticationManager(authenticationManager()).allowedTokenEndpointRequestMethods(HttpMethod.GET,
HttpMethod.POST);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
// 允许表单认证
oauthServer.allowFormAuthenticationForClients();
// 允许check_token访问
oauthServer.checkTokenAccess("permitAll()");
}
@Bean
AuthenticationManager authenticationManager() {
AuthenticationManager authenticationManager = new AuthenticationManager() {
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
return daoAuhthenticationProvider().authenticate(authentication);
}
};
return authenticationManager;
}
@Bean
public AuthenticationProvider daoAuhthenticationProvider() {
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(userDetailsService());
daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
return daoAuthenticationProvider;
}
// 设置添加用户信息,正常应该从数据库中读取
@Bean
UserDetailsService userDetailsService() {
InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
userDetailsService.createUser(User.withUsername("user_1").password(passwordEncoder().encode("123456"))
.authorities("ROLE_USER").build());
userDetailsService.createUser(User.withUsername("user_2").password(passwordEncoder().encode("1234567"))
.authorities("ROLE_USER").build());
return userDetailsService;
}
@Bean
PasswordEncoder passwordEncoder() {
// 加密方式
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
return passwordEncoder;
}
}
启动授权服务
@SpringBootApplication
public class AppOauth2 {
public static void main(String[] args) {
SpringApplication.run(AppOauth2.class, args);
}
}
验证授权
获取accessToken请求地址: http://localhost:8080/oauth/token
参数
grant_type、username、password、client_id、client_secret、scope
验证accessToken是否有效
http://localhost:8080/oauth/check_token?token=b212eaec-63a7-489d-b5a2-883ec248c417
刷新新的accessToken
需要配置
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.authenticationManager(authenticationManager()).allowedTokenEndpointRequestMethods(HttpMethod.GET,
HttpMethod.POST);
endpoints.authenticationManager(authenticationManager());
endpoints.userDetailsService(userDetailsService());
}
2)、授权模式(常用)
新增授权权限
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// withClient appid
clients.inMemory().withClient("client_1").secret(passwordEncoder().encode("123456"))
.authorizedGrantTypes("password", "client_credentials", "refresh_token", "authorization_code")
.scopes("all").redirectUris("http://www.mayikt.com")
.accessTokenValiditySeconds(accessTokenValiditySeconds)
.refreshTokenValiditySeconds(refreshTokenValiditySeconds);
}
访问报错
User must be authenticated with Spring Security before authorization can be completed.
解决办法 添加Security权限
@Component
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// 授权中心管理器
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
AuthenticationManager manager = super.authenticationManagerBean();
return manager;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
// 拦截所有请求,使用httpBasic方式登陆
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().httpBasic();
}
}