1、什么是Spring Cloud OAuth2
当我们平台向其他平台开放一些接口,允许某些应用可以调用,这时候应用OAuth2.0协议进行用户身份验证和获取用户授权,一般都是先向开发接口平台提出申请,审批之后会给申请的应用分配一个唯一的appID,appkey,当客户端访问开发接口平台,先根据appid和appkey获取授权码,在根据授权码与appid获取到accessToken,然后客户端将accessToken放到请求头中去请求开放平台的接口就可以了,当请求到达开发平台的时候,开发平台会将向验权中心发出请求,验证此accessToken是否有效,如果有效才能继续访问;
qq联合登录中访问获取用户信息的接口步骤
**
1、生成授权CODE链接,获取授权码 ----用户点击
https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=101462456&state=888&redirect_uri=http://mayikt.s1.natapp.cc/qqLoginBack
2、使用用户获取的授权码,获取对应的accessToken
https://graph.qq.com/oauth2.0/token?grant_type=authorization_code&client_id=101462456&client_secret=4488033be77331e7cdcaed8ceadc10d5&code=E91DF5B0E2455A6B2AF25CD9FA1C7582&
redirect_uri=http://mayikt.s1.natapp.cc/qqLoginBack
3、使用accessToken获取用户openid
https://graph.qq.com/oauth2.0/me?access_token=B2FD1997D149313F16C93D91C75AC75E
4、使用openid获取用户信息
https://graph.qq.com/user/get_user_info?access_token=B2FD1997D149313F16C93D91C75AC75E&oauth_consumer_key=101462456&openid=4B1717CBBFE1E900D2A1482C4A18B3BD
2、搭建Spring Cloud OAuth2
Oauth2角色划分
1、Resource
Server:被授权访问的资源
2、Authotization
Server:OAUTH2认证授权中心
3、Resource
Owner: 用户
4、Client:使用API的客户端(如Android
、IOS、web app)
搭建OAuth2认证授权中心:
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</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>
spring:
datasource:
hikari:
connection-test-query: SELECT 1
minimum-idle: 1
maximum-pool-size: 5
pool-name: dbcp1
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/alan-oauth?autoReconnect=true&useSSL=false
username: root
password: root
// 授权认证服务中心配置
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
// @EnableAuthorizationServer 开启 授权认证服务中心
// accessToken 有效期 2小时
private static final int ACCESSTOKENVALIDITYSECONDS = 7200;// 两小时
private static final int REFRESHTOKENVALIDITYSECONDS = 7200;// 两小时
// 配置 appid、appkey 、回调地址、token有效期
// 思考问题:accessToken 怎么办? 使用刷新令牌获取新的accessToken 至少提前10分钟调用刷新令牌接口进行刷新
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// 思考: 如果合作机构需要做oauth2认证的话 第一步操作的是什么?
// 1.申请获取到appid 和 appkey 写死的
// clients.inMemory().withClient("client_1").secret(passwordEncoder().encode("123456"))
// .redirectUris("http://www.mayikt.com")
// .authorizedGrantTypes("authorization_code", "password",
// "refresh_token").scopes("all")
// .accessTokenValiditySeconds(ACCESSTOKENVALIDITYSECONDS)
// .refreshTokenValiditySeconds(REFRESHTOKENVALIDITYSECONDS);// 授权类型
// 为授权码类型
// 密码授权模式 使用用户名称和密码进行获取accessToken
// 如果clientid appid 同时使用密码模式和授权code 获取accessToken 为发生什么问题
// a 相同
// b 覆盖
// c 不一致性
// d 报错
// 密码模式 660fa8e0-f8db-422d-8891-906db021ded8
// 授权模式 660fa8e0-f8db-422d-8891-906db021ded8
// accessToken 和appid关联
}
// 设置token类型
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.authenticationManager(authenticationManager()).allowedTokenEndpointRequestMethods(HttpMethod.GET,
HttpMethod.POST);
// 必须加上他,不然刷新令牌接口会报错
endpoints.authenticationManager(authenticationManager());
endpoints.userDetailsService(userDetailsService());
// 之前的accessToken b55c980c-31f7-4498-a783-bd905608fb18
// 刷新之后accessToken d40f7915-dd06-4503-83c8-2815915c9368
}
@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;
}
}
// 配置授权中心信息
@Configuration
@EnableAuthorizationServer // 开启认证授权中心
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
// @Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Autowired
@Qualifier("dataSource")
private DataSource dataSource;
// @Autowired
// private UserDetailsService userDetailsService;
@Bean
public TokenStore tokenStore() {
// return new InMemoryTokenStore(); //使用内存中的 token store
return new JdbcTokenStore(dataSource); /// 使用Jdbctoken store
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// 添加授权用户
clients.jdbc(dataSource).withClient("client_1").secret(new BCryptPasswordEncoder().encode("123456"))
.authorizedGrantTypes("password", "refresh_token", "authorization_code")// 允许授权范围
.redirectUris("http://www.mayikt.com").authorities("ROLE_ADMIN", "ROLE_USER")// 客户端可以使用的权限
.scopes("all").accessTokenValiditySeconds(7200).refreshTokenValiditySeconds(7200);
// 自动往数据插入该应用id信息
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager)
.userDetailsService(userDetailsService());// 必须设置
// UserDetailsService
// 否则刷新token 时会报错
}
// 已经讲过UserDetailsService 写读数据
@Bean
UserDetailsService userDetailsService() {
InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
userDetailsService.createUser(User.withUsername("user_1").password(new BCryptPasswordEncoder().encode("123456"))
.authorities("ROLE_USER").build());
userDetailsService.createUser(User.withUsername("user_2")
.password(new BCryptPasswordEncoder().encode("1234567")).authorities("ROLE_USER").build());
return userDetailsService;
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()")
.allowFormAuthenticationForClients();// 允许表单登录
}
@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
PasswordEncoder passwordEncoder() {
// 加密方式
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
return passwordEncoder;
}
// 6个git 关于oauth2 五个是 1.5版本 1个 2.0
}
@Component
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// 拦截所有请求,使用httpBasic方式登陆
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().httpBasic();
}
}
搭建资源中心与客户端
<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>
<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>
#### 客户端 应用端角色
server:
port: 8081
logging:
level:
org.springframework.security: DEBUG
security:
oauth2:
resource:
####从认证授权中心上验证token
tokenInfoUri: http://localhost:8080/oauth/check_token
preferTokenInfo: true
client:
accessTokenUri: http://localhost:8080/oauth/token
userAuthorizationUri: http://localhost:8080/oauth/authorize
# ###appid
# clientId: client_1
# ###appSecret
# clientSecret: 123456
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
// @EnableResourceServer 开启资源服务中心
@Override
public void configure(HttpSecurity http) throws Exception {
// 对 api/order 请求进行拦截 验证 accessToken
http.authorizeRequests().antMatchers("/api/order/**").authenticated();
}
// public
// 拦截资源 网关里面做 开放接口和内部接口一定要独立出来可以封转该业务逻辑相同
}
@RestController
@RequestMapping("/api/order")
public class OrderController {
@RequestMapping("/addOrder")
public String addOrder() {
return "addOrder";
}
}
11.15.pptx基于SpringCloud-OAuth2搭建微服务开放平台.doc上课代码.zip新建 DOC 文档.doc新建 DOCX 文档.docx