1、什么是Spring Cloud OAuth2
    当我们平台向其他平台开放一些接口,允许某些应用可以调用,这时候应用OAuth2.0协议进行用户身份验证和获取用户授权,一般都是先向开发接口平台提出申请,审批之后会给申请的应用分配一个唯一的appID,appkey,当客户端访问开发接口平台,先根据appid和appkey获取授权码,在根据授权码与appid获取到accessToken,然后客户端将accessToken放到请求头中去请求开放平台的接口就可以了,当请求到达开发平台的时候,开发平台会将向验权中心发出请求,验证此accessToken是否有效,如果有效才能继续访问;

    qq联合登录中访问获取用户信息的接口步骤
    **

    1. 1、生成授权CODE链接,获取授权码 ----用户点击
    2. https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=101462456&state=888&redirect_uri=http://mayikt.s1.natapp.cc/qqLoginBack
    3. 2、使用用户获取的授权码,获取对应的accessToken
    4. https://graph.qq.com/oauth2.0/token?grant_type=authorization_code&client_id=101462456&client_secret=4488033be77331e7cdcaed8ceadc10d5&code=E91DF5B0E2455A6B2AF25CD9FA1C7582&
    5. redirect_uri=http://mayikt.s1.natapp.cc/qqLoginBack
    6. 3、使用accessToken获取用户openid
    7. https://graph.qq.com/oauth2.0/me?access_token=B2FD1997D149313F16C93D91C75AC75E
    8. 4、使用openid获取用户信息
    9. 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认证授权中心:

    1. <parent>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-parent</artifactId>
    4. <version>2.0.1.RELEASE</version>
    5. </parent>
    6. <!-- 管理依赖 -->
    7. <dependencyManagement>
    8. <dependencies>
    9. <dependency>
    10. <groupId>org.springframework.cloud</groupId>
    11. <artifactId>spring-cloud-dependencies</artifactId>
    12. <version>Finchley.M7</version>
    13. <type>pom</type>
    14. <scope>import</scope>
    15. </dependency>
    16. </dependencies>
    17. </dependencyManagement>
    18. <dependencies>
    19. <!-- SpringBoot整合Web组件 -->
    20. <dependency>
    21. <groupId>org.springframework.boot</groupId>
    22. <artifactId>spring-boot-starter-web</artifactId>
    23. </dependency>
    24. <dependency>
    25. <groupId>org.projectlombok</groupId>
    26. <artifactId>lombok</artifactId>
    27. </dependency>
    28. <!-- springboot整合freemarker -->
    29. <dependency>
    30. <groupId>org.springframework.boot</groupId>
    31. <artifactId>spring-boot-starter-freemarker</artifactId>
    32. </dependency>
    33. <!-->spring-boot 整合security -->
    34. <dependency>
    35. <groupId>org.springframework.boot</groupId>
    36. <artifactId>spring-boot-starter-security</artifactId>
    37. </dependency>
    38. <!-- spring-cloud-starter-oauth2 -->
    39. <dependency>
    40. <groupId>org.springframework.cloud</groupId>
    41. <artifactId>spring-cloud-starter-oauth2</artifactId>
    42. </dependency>
    43. <dependency>
    44. <groupId>org.springframework.boot</groupId>
    45. <artifactId>spring-boot-starter-jdbc</artifactId>
    46. </dependency>
    47. <dependency>
    48. <groupId>mysql</groupId>
    49. <artifactId>mysql-connector-java</artifactId>
    50. </dependency>
    51. </dependencies>
    52. <!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
    53. <repositories>
    54. <repository>
    55. <id>spring-milestones</id>
    56. <name>Spring Milestones</name>
    57. <url>https://repo.spring.io/libs-milestone</url>
    58. <snapshots>
    59. <enabled>false</enabled>
    60. </snapshots>
    61. </repository>
    62. </repositories>
    1. spring:
    2. datasource:
    3. hikari:
    4. connection-test-query: SELECT 1
    5. minimum-idle: 1
    6. maximum-pool-size: 5
    7. pool-name: dbcp1
    8. driver-class-name: com.mysql.jdbc.Driver
    9. url: jdbc:mysql://localhost:3306/alan-oauth?autoReconnect=true&useSSL=false
    10. username: root
    11. password: root
    1. // 授权认证服务中心配置
    2. @Configuration
    3. @EnableAuthorizationServer
    4. public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    5. // @EnableAuthorizationServer 开启 授权认证服务中心
    6. // accessToken 有效期 2小时
    7. private static final int ACCESSTOKENVALIDITYSECONDS = 7200;// 两小时
    8. private static final int REFRESHTOKENVALIDITYSECONDS = 7200;// 两小时
    9. // 配置 appid、appkey 、回调地址、token有效期
    10. // 思考问题:accessToken 怎么办? 使用刷新令牌获取新的accessToken 至少提前10分钟调用刷新令牌接口进行刷新
    11. @Override
    12. public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    13. // 思考: 如果合作机构需要做oauth2认证的话 第一步操作的是什么?
    14. // 1.申请获取到appid 和 appkey 写死的
    15. // clients.inMemory().withClient("client_1").secret(passwordEncoder().encode("123456"))
    16. // .redirectUris("http://www.mayikt.com")
    17. // .authorizedGrantTypes("authorization_code", "password",
    18. // "refresh_token").scopes("all")
    19. // .accessTokenValiditySeconds(ACCESSTOKENVALIDITYSECONDS)
    20. // .refreshTokenValiditySeconds(REFRESHTOKENVALIDITYSECONDS);// 授权类型
    21. // 为授权码类型
    22. // 密码授权模式 使用用户名称和密码进行获取accessToken
    23. // 如果clientid appid 同时使用密码模式和授权code 获取accessToken 为发生什么问题
    24. // a 相同
    25. // b 覆盖
    26. // c 不一致性
    27. // d 报错
    28. // 密码模式 660fa8e0-f8db-422d-8891-906db021ded8
    29. // 授权模式 660fa8e0-f8db-422d-8891-906db021ded8
    30. // accessToken 和appid关联
    31. }
    32. // 设置token类型
    33. public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
    34. endpoints.authenticationManager(authenticationManager()).allowedTokenEndpointRequestMethods(HttpMethod.GET,
    35. HttpMethod.POST);
    36. // 必须加上他,不然刷新令牌接口会报错
    37. endpoints.authenticationManager(authenticationManager());
    38. endpoints.userDetailsService(userDetailsService());
    39. // 之前的accessToken b55c980c-31f7-4498-a783-bd905608fb18
    40. // 刷新之后accessToken d40f7915-dd06-4503-83c8-2815915c9368
    41. }
    42. @Override
    43. public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
    44. // 允许表单认证
    45. oauthServer.allowFormAuthenticationForClients();
    46. // 允许check_token访问
    47. oauthServer.checkTokenAccess("permitAll()");
    48. }
    49. @Bean
    50. AuthenticationManager authenticationManager() {
    51. AuthenticationManager authenticationManager = new AuthenticationManager() {
    52. public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    53. return daoAuhthenticationProvider().authenticate(authentication);
    54. }
    55. };
    56. return authenticationManager;
    57. }
    58. @Bean
    59. public AuthenticationProvider daoAuhthenticationProvider() {
    60. DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
    61. daoAuthenticationProvider.setUserDetailsService(userDetailsService());
    62. daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
    63. daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
    64. return daoAuthenticationProvider;
    65. }
    66. // 设置添加用户信息,正常应该从数据库中读取
    67. @Bean
    68. UserDetailsService userDetailsService() {
    69. InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
    70. userDetailsService.createUser(User.withUsername("user_1").password(passwordEncoder().encode("123456"))
    71. .authorities("ROLE_USER").build());
    72. userDetailsService.createUser(User.withUsername("user_2").password(passwordEncoder().encode("1234567"))
    73. .authorities("ROLE_USER").build());
    74. return userDetailsService;
    75. }
    76. @Bean
    77. PasswordEncoder passwordEncoder() {
    78. // 加密方式
    79. PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    80. return passwordEncoder;
    81. }
    82. }


    1. // 配置授权中心信息
    2. @Configuration
    3. @EnableAuthorizationServer // 开启认证授权中心
    4. public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    5. @Autowired
    6. // @Qualifier("authenticationManagerBean")
    7. private AuthenticationManager authenticationManager;
    8. @Autowired
    9. @Qualifier("dataSource")
    10. private DataSource dataSource;
    11. // @Autowired
    12. // private UserDetailsService userDetailsService;
    13. @Bean
    14. public TokenStore tokenStore() {
    15. // return new InMemoryTokenStore(); //使用内存中的 token store
    16. return new JdbcTokenStore(dataSource); /// 使用Jdbctoken store
    17. }
    18. @Override
    19. public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    20. // 添加授权用户
    21. clients.jdbc(dataSource).withClient("client_1").secret(new BCryptPasswordEncoder().encode("123456"))
    22. .authorizedGrantTypes("password", "refresh_token", "authorization_code")// 允许授权范围
    23. .redirectUris("http://www.mayikt.com").authorities("ROLE_ADMIN", "ROLE_USER")// 客户端可以使用的权限
    24. .scopes("all").accessTokenValiditySeconds(7200).refreshTokenValiditySeconds(7200);
    25. // 自动往数据插入该应用id信息
    26. }
    27. @Override
    28. public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    29. endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager)
    30. .userDetailsService(userDetailsService());// 必须设置
    31. // UserDetailsService
    32. // 否则刷新token 时会报错
    33. }
    34. // 已经讲过UserDetailsService 写读数据
    35. @Bean
    36. UserDetailsService userDetailsService() {
    37. InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
    38. userDetailsService.createUser(User.withUsername("user_1").password(new BCryptPasswordEncoder().encode("123456"))
    39. .authorities("ROLE_USER").build());
    40. userDetailsService.createUser(User.withUsername("user_2")
    41. .password(new BCryptPasswordEncoder().encode("1234567")).authorities("ROLE_USER").build());
    42. return userDetailsService;
    43. }
    44. @Override
    45. public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    46. security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()")
    47. .allowFormAuthenticationForClients();// 允许表单登录
    48. }
    49. @Bean
    50. AuthenticationManager authenticationManager() {
    51. AuthenticationManager authenticationManager = new AuthenticationManager() {
    52. public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    53. return daoAuhthenticationProvider().authenticate(authentication);
    54. }
    55. };
    56. return authenticationManager;
    57. }
    58. @Bean
    59. public AuthenticationProvider daoAuhthenticationProvider() {
    60. DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
    61. daoAuthenticationProvider.setUserDetailsService(userDetailsService());
    62. daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
    63. daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
    64. return daoAuthenticationProvider;
    65. }
    66. @Bean
    67. PasswordEncoder passwordEncoder() {
    68. // 加密方式
    69. PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    70. return passwordEncoder;
    71. }
    72. // 6个git 关于oauth2 五个是 1.5版本 1个 2.0
    73. }


    1. @Component
    2. public class SecurityConfig extends WebSecurityConfigurerAdapter {
    3. // 拦截所有请求,使用httpBasic方式登陆
    4. @Override
    5. protected void configure(HttpSecurity http) throws Exception {
    6. http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().httpBasic();
    7. }
    8. }

    搭建资源中心与客户端

    1. <parent>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-parent</artifactId>
    4. <version>2.0.1.RELEASE</version>
    5. </parent>
    6. <!-- 管理依赖 -->
    7. <dependencyManagement>
    8. <dependencies>
    9. <dependency>
    10. <groupId>org.springframework.cloud</groupId>
    11. <artifactId>spring-cloud-dependencies</artifactId>
    12. <version>Finchley.M7</version>
    13. <type>pom</type>
    14. <scope>import</scope>
    15. </dependency>
    16. </dependencies>
    17. </dependencyManagement>
    18. <dependencies>
    19. <!-- SpringBoot整合Web组件 -->
    20. <dependency>
    21. <groupId>org.springframework.boot</groupId>
    22. <artifactId>spring-boot-starter-web</artifactId>
    23. </dependency>
    24. <dependency>
    25. <groupId>org.projectlombok</groupId>
    26. <artifactId>lombok</artifactId>
    27. </dependency>
    28. <!-- springboot整合freemarker -->
    29. <dependency>
    30. <groupId>org.springframework.boot</groupId>
    31. <artifactId>spring-boot-starter-freemarker</artifactId>
    32. </dependency>
    33. <!-->spring-boot 整合security -->
    34. <dependency>
    35. <groupId>org.springframework.boot</groupId>
    36. <artifactId>spring-boot-starter-security</artifactId>
    37. </dependency>
    38. <dependency>
    39. <groupId>org.springframework.cloud</groupId>
    40. <artifactId>spring-cloud-starter-oauth2</artifactId>
    41. </dependency>
    42. </dependencies>
    43. <!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
    44. <repositories>
    45. <repository>
    46. <id>spring-milestones</id>
    47. <name>Spring Milestones</name>
    48. <url>https://repo.spring.io/libs-milestone</url>
    49. <snapshots>
    50. <enabled>false</enabled>
    51. </snapshots>
    52. </repository>
    53. </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