OAuth2简化模式

版本:springboot2.2.6.RELEASE
参考文章:OAuth2 授权码模式

做如下修改:

1、auth-server(授权服务器)
修改configure(ClientDetailsServiceConfigurer) 方法部分:只需要在 authorizedGrantTypes 中增加 implicit 表示支持简化模式即可。

AuthorizationServer:

package cn.linst.authserver.config;  import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.TokenStore;  import java.lang.ref.SoftReference;   /**  * 简化模式。  *  * 在这个auth-server demo中,就是相当于第三方平台。  * 授权服务器。模拟第三方平台。授权服务器一方面是校验客户端,另一方面则是校验用户。  * 用户信息校验在SecurityConfig配置了。  */ @EnableAuthorizationServer  // 表示开启授权服务器的自动化配置 @Configuration public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {      @Autowired     TokenStore tokenStore;      /**      * 保存的客户端信息      */     @Autowired     ClientDetailsService clientDetailsService;      /**      *  令牌相关配置。用来配置 Token 的一些基本信息。      *  如 Token 是否支持刷新、Token 的存储位置、Token 的有效期以及刷新 Token 的有效期等。      *  当 Token 快要过期的时候,需要获取一个新的token,获取新的 Token 时候,需要有一个凭证信息,refresh_token。这个 refresh_token 也是有有效期的      */     @Bean     AuthorizationServerTokenServices tokenServices() {         DefaultTokenServices services = new DefaultTokenServices();         services.setClientDetailsService(clientDetailsService);         services.setSupportRefreshToken(true);         services.setTokenStore(tokenStore);         // access_token 有效期         services.setAccessTokenValiditySeconds(60 * 60 * 2);         // refresh_token 有效期         services.setRefreshTokenValiditySeconds(60 * 60 * 24 * 3);         return services;     }      /**      *  AuthorizationServerSecurityConfigurer用来配置令牌端点的安全约束,就是这个端点谁能访问,谁不能访问。      * checkTokenAccess是指一个 Token 校验的端点,这个端点我们设置为可以直接访问。在资源服务器收到 Token 之后,需要去校验 Token 的合法性,就会访问这个端点。      */     @Override     public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {         // 1.  /oauth/check_token   资源服务器会自动校验这个接口,检查token对应的信息。         // 2. 这里配置为了让这个接口都能访问到。         // 3. 允许表单登录。         security.checkTokenAccess("permitAll()")                 .allowFormAuthenticationForClients();     }  // //    /** 授权码模式 //     * ClientDetailsServiceConfigurer 用来配置客户端的信息。 //     * 校验客户端 //     */ //    @Override //    public void configure(ClientDetailsServiceConfigurer clients) throws Exception { //        clients.inMemory() //                .withClient("clientIdForMyApplication") //应用在第三方平台注册,平台给应用生成appid。 //                .secret(new BCryptPasswordEncoder().encode("123")) //                .resourceIds("res1") // 资源id //                .authorizedGrantTypes("authorization_code","refresh_token")  // authorization_code:授权码模式 ;refresh_token:刷新token //                .scopes("all")                 .autoApprove(true) //                .redirectUris("http://localhost:8082/index.html"); // 授权完成后,重定向的地址。 //    }       /**      * 简化模式      * ClientDetailsServiceConfigurer 用来配置客户端的信息。      * 校验客户端      */     @Override     public void configure(ClientDetailsServiceConfigurer clients) throws Exception {         clients.inMemory()                 .withClient("clientIdForMyApplication") //应用在第三方平台注册,平台给应用生成appid。                 .secret(new BCryptPasswordEncoder().encode("123"))                 .resourceIds("res1") // 资源id                 .authorizedGrantTypes("refresh_token","implicit")  // authorization_code:授权码模式 ;implicit:支持简化模式                 .scopes("all") //                .autoApprove(true)                 .redirectUris("http://localhost:8082/01.html"); // 授权完成后,重定向的地址。     }      /**      * AuthorizationServerEndpointsConfigurer用来配置令牌的访问端点和令牌服务。      * authorizationCodeServices用来配置授权码的存储。      * tokenServices 这个 Bean 主要用来配置 Token 的一些基本信息。      */     @Override     public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {         endpoints.authorizationCodeServices(authorizationCodeServices())                 .tokenServices(tokenServices());     }      /**      *  授权码保存的地方,存哪都行,一般存内存,授权码用一次就失效了没用了。      *  授权码与令牌区别:授权码是用来获取令牌的,使用一次就失效,令牌则是用来获取资源。      *      */     @Bean     AuthorizationCodeServices authorizationCodeServices() {         return new InMemoryAuthorizationCodeServices();     } } 

2、因为简化模式没有服务端,我们只能通过 js 来请求资源服务器上的数据,所以资源服务器需要支持跨域,我们修改如下两个地方使之支持跨域。

user-server(资源服务器):
1)在 Controller 上添加 @CrossOrigin 注解使之支持跨域

package cn.linst.userserver;  import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;   @RestController // 增加跨越支持 @CrossOrigin(value = "*") public class HelloController {     @GetMapping("/hello")     public String hello() {         return "hello。。。";     }     @GetMapping("/admin/hello")     public String admin() {         return "admin。。。";     } } 

2)配置 Spring Security 使之支持跨域,在configure(HttpSecurity http)方法增加cors

package cn.linst.userserver.config;  import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.token.RemoteTokenServices;   /**  * 模拟第三方平台的资源服务器  */ @Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter {     /**      * 这是因为资源服务器和授权服务器是分开的,资源服务器和授权服务器是放在一起的。      * 如果资源服务器和授权服务器是放在一起的,就不需要配置 RemoteTokenServices 了      *      */     @Bean     RemoteTokenServices tokenServices() {         // 配置了一个 RemoteTokenServices 的实例。         // 配置了 access_token 的校验地址、client_id、client_secret 这三个信息。         // 当用户来资源服务器请求资源时,会携带上一个 access_token,通过这里的配置,就能够         // 校验出 token 是否正确等。         RemoteTokenServices services = new RemoteTokenServices();         services.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");         services.setClientId("clientIdForMyApplication");         services.setClientSecret("123");         return services;     }      @Override     public void configure(ResourceServerSecurityConfigurer resources) throws Exception {         resources.resourceId("res1").tokenServices(tokenServices());     }      /**      * 配置一下资源的拦截规则,这就是 Spring Security 中的基本写法 。      */     @Override     public void configure(HttpSecurity http) throws Exception {         http.authorizeRequests()                 .antMatchers("/admin/**").hasRole("admin")                 .anyRequest().authenticated().and().cors();     } } 

3、client-app(第三方应用)
在static目录下,新增01.html

<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head>     <meta charset="UTF-8">     <title>hello world 简化模式</title>     <script src="/jquery-3.5.0.min.js"></script> </head> <body> 你好,世界!  <a href="http://localhost:8080/oauth/authorize?client_id=clientIdForMyApplication&response_type=token&scope=all&redirect_uri=http://localhost:8082/01.html">第三方登录(简化模式)</a>  <div id="div1"></div> <script>     var hash = window.location.hash;//提取出参数,类似这种格式#access_token=38653449-a3cd-414b-a313-7a1aa9bac0b1&token_type=bearer&expires_in=7069     if (hash && hash.length > 0) {         var params = hash.substring(1).split("&");         var token = params[0].split("=");//[access_token,38653449-a3cd-414b-a313-7a1aa9bac0b1]         $.ajax({             type: 'get',             headers: {                 'Authorization': 'Bearer ' + token[1]             },             url: 'http://localhost:8081/hello',             success: function (data) {                 $("#div1").html(data)             }         })     } </script> </body> </html> 

登录成功的页面:
OAuth2简化模式

版权声明:玥玥 发表于 2021-05-26 14:50:33。
转载请注明:OAuth2简化模式 | 女黑客导航