├── README.md ├── springSecurityOauth2请求接口.txt ├── Spring2.0SecurityOauth2 ├── src │ └── main │ │ ├── resources │ │ └── application.yml │ │ └── java │ │ └── com │ │ └── oauth │ │ └── client │ │ ├── domain │ │ └── User.java │ │ ├── ClientApplication.java │ │ ├── rest │ │ └── TestRest.java │ │ └── config │ │ ├── ResourceServerConfiguration.java │ │ ├── SecurityConfiguration.java │ │ ├── AuthorizationServerConfiguration.java │ │ └── MyRedisTokenStore.java └── pom.xml ├── SpringSecurityOauth2 ├── src │ └── main │ │ ├── java │ │ └── oauth │ │ │ └── security │ │ │ └── client │ │ │ ├── service │ │ │ ├── ApplyService.java │ │ │ └── impl │ │ │ │ └── ApplyServiceImpl.java │ │ │ ├── dao │ │ │ └── ApplyDao.java │ │ │ ├── ClientApplication.java │ │ │ ├── configauto │ │ │ ├── jdbcdetail │ │ │ │ ├── MyTokenStore.java │ │ │ │ ├── MyJdbcClientDetailsService.java │ │ │ │ └── MyJdbcTokenStore.java │ │ │ ├── ResourceServerConfiguration.java │ │ │ ├── ApplyClientDetailService.java │ │ │ ├── SecurityConfiguration.java │ │ │ └── AuthorizationServerConfiguration.java │ │ │ ├── web │ │ │ └── TestEndpoints.java │ │ │ └── domain │ │ │ └── ApplyDetails.java │ │ └── resources │ │ └── application.yml └── pom.xml └── oauth2.sql /README.md: -------------------------------------------------------------------------------- 1 | # SpringSecurityOauth2 2 | Oauth2验证 客户端授权 mysql数据库存储 3 | 4 | 更新了Spring2.0版本 5 | -------------------------------------------------------------------------------- /springSecurityOauth2请求接口.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fangchunzao/SpringSecurityOauth2/HEAD/springSecurityOauth2请求接口.txt -------------------------------------------------------------------------------- /Spring2.0SecurityOauth2/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | spring: 4 | redis: 5 | host: 127.0.0.1 6 | database: 0 7 | port: 6379 8 | -------------------------------------------------------------------------------- /SpringSecurityOauth2/src/main/java/oauth/security/client/service/ApplyService.java: -------------------------------------------------------------------------------- 1 | package oauth.security.client.service; 2 | 3 | 4 | import java.util.Map; 5 | 6 | public interface ApplyService { 7 | 8 | Map findApplyById(String id); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /SpringSecurityOauth2/src/main/java/oauth/security/client/dao/ApplyDao.java: -------------------------------------------------------------------------------- 1 | package oauth.security.client.dao; 2 | 3 | import org.apache.ibatis.annotations.Mapper; 4 | 5 | import java.util.Map; 6 | 7 | @Mapper 8 | public interface ApplyDao { 9 | 10 | Map findApplyById(String id); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Spring2.0SecurityOauth2/src/main/java/com/oauth/client/domain/User.java: -------------------------------------------------------------------------------- 1 | package com.oauth.client.domain; 2 | 3 | /** 4 | * @author FCZ 5 | * @since 2018/9/29 17:53 6 | */ 7 | public class User { 8 | 9 | private String name; 10 | 11 | public String getName() { 12 | return name; 13 | } 14 | 15 | public void setName(String name) { 16 | this.name = name; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SpringSecurityOauth2/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8081 3 | 4 | spring: 5 | datasource: 6 | url: jdbc:mysql://127.0.0.1:3306/oauth2?useUnicode=true&characterEncoding=utf-8&useSSL=false 7 | username: root 8 | password: 123456 9 | driver-class-name: com.mysql.jdbc.Driver 10 | redis: 11 | host: 127.0.0.1 12 | database: 0 13 | 14 | mybatis: 15 | mapper-locations: mapper/*.xml 16 | 17 | security: 18 | oauth2: 19 | resource: 20 | filter-order: 3 -------------------------------------------------------------------------------- /Spring2.0SecurityOauth2/src/main/java/com/oauth/client/ClientApplication.java: -------------------------------------------------------------------------------- 1 | package com.oauth.client; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.web.servlet.ServletComponentScan; 6 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 7 | 8 | @SpringBootApplication 9 | @ServletComponentScan 10 | public class ClientApplication { 11 | public static void main(String[] args) { 12 | SpringApplication.run(ClientApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /SpringSecurityOauth2/src/main/java/oauth/security/client/service/impl/ApplyServiceImpl.java: -------------------------------------------------------------------------------- 1 | package oauth.security.client.service.impl; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Service; 5 | import oauth.security.client.dao.ApplyDao; 6 | import oauth.security.client.service.ApplyService; 7 | 8 | import java.util.Map; 9 | 10 | @Service 11 | public class ApplyServiceImpl implements ApplyService{ 12 | 13 | @Autowired 14 | private ApplyDao applyDao; 15 | 16 | @Override 17 | public Map findApplyById(String id) { 18 | return applyDao.findApplyById(id); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SpringSecurityOauth2/src/main/java/oauth/security/client/ClientApplication.java: -------------------------------------------------------------------------------- 1 | package oauth.security.client; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; 7 | import org.springframework.boot.web.servlet.ServletComponentScan; 8 | 9 | @SpringBootApplication() 10 | @ServletComponentScan 11 | public class ClientApplication { 12 | public static void main(String[] args) { 13 | SpringApplication.run(ClientApplication.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SpringSecurityOauth2/src/main/java/oauth/security/client/configauto/jdbcdetail/MyTokenStore.java: -------------------------------------------------------------------------------- 1 | package oauth.security.client.configauto.jdbcdetail; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.data.redis.connection.RedisConnectionFactory; 5 | import org.springframework.security.oauth2.provider.token.TokenStore; 6 | import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore; 7 | 8 | public class MyTokenStore { 9 | 10 | @Autowired 11 | RedisConnectionFactory redisConnectionFactory; 12 | 13 | public MyTokenStore() { 14 | 15 | } 16 | 17 | public TokenStore getTokenStore() { 18 | return new RedisTokenStore(redisConnectionFactory); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /Spring2.0SecurityOauth2/src/main/java/com/oauth/client/rest/TestRest.java: -------------------------------------------------------------------------------- 1 | package com.oauth.client.rest; 2 | 3 | import com.oauth.client.domain.User; 4 | import org.springframework.web.bind.annotation.RequestBody; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import java.util.LinkedHashMap; 9 | import java.util.Map; 10 | 11 | /** 12 | * @author FCZ 13 | * @since 2018/9/29 17:25 14 | */ 15 | @RequestMapping("/Test") 16 | @RestController 17 | public class TestRest { 18 | 19 | @RequestMapping({ "/user", "/me" }) 20 | public Map user(@RequestBody User user) { 21 | Map map = new LinkedHashMap<>(); 22 | map.put("name", user.getName()); 23 | return map; 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /SpringSecurityOauth2/src/main/java/oauth/security/client/web/TestEndpoints.java: -------------------------------------------------------------------------------- 1 | package oauth.security.client.web; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.security.core.Authentication; 5 | import org.springframework.security.core.context.SecurityContextHolder; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.RestController; 9 | import oauth.security.client.service.ApplyService; 10 | 11 | import java.util.Map; 12 | 13 | 14 | @RestController 15 | public class TestEndpoints { 16 | 17 | @Autowired 18 | private ApplyService applyService; 19 | 20 | @GetMapping("/product/{id}") 21 | public String getProduct(@PathVariable String id) { 22 | Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 23 | return "product id : " + id; 24 | } 25 | 26 | @GetMapping("/order/{id}") 27 | public String getOrder(@PathVariable String id) { 28 | Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 29 | return "order id : " + id; 30 | } 31 | 32 | @GetMapping("apply/getAll") 33 | public String getAll() { 34 | Map list = applyService.findApplyById("1"); 35 | return "list "; 36 | } 37 | 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /Spring2.0SecurityOauth2/src/main/java/com/oauth/client/config/ResourceServerConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.oauth.client.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 5 | import org.springframework.security.config.http.SessionCreationPolicy; 6 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; 7 | import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; 8 | import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; 9 | 10 | @Configuration 11 | @EnableResourceServer 12 | public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { 13 | 14 | private static final String DEMO_RESOURCE_ID = "*"; 15 | 16 | @Override 17 | public void configure(ResourceServerSecurityConfigurer resources) { 18 | resources.resourceId(DEMO_RESOURCE_ID).stateless(true); 19 | } 20 | 21 | @Override 22 | public void configure(HttpSecurity http) throws Exception { 23 | http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) 24 | .and().requestMatchers().anyRequest() 25 | .and().anonymous() 26 | .and().authorizeRequests() 27 | // .antMatchers("/product/**").access("#oauth2.hasScope('select') and hasRole('ROLE_USER')") 28 | .antMatchers("/**").authenticated(); //配置访问权限控制,必须认证过后才可以访问 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SpringSecurityOauth2/src/main/java/oauth/security/client/configauto/ResourceServerConfiguration.java: -------------------------------------------------------------------------------- 1 | package oauth.security.client.configauto; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 5 | import org.springframework.security.config.http.SessionCreationPolicy; 6 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; 7 | import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; 8 | import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; 9 | 10 | @Configuration 11 | @EnableResourceServer 12 | public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { 13 | 14 | private static final String DEMO_RESOURCE_ID = "*"; 15 | 16 | @Override 17 | public void configure(ResourceServerSecurityConfigurer resources) { 18 | resources.resourceId(DEMO_RESOURCE_ID).stateless(true); 19 | } 20 | 21 | @Override 22 | public void configure(HttpSecurity http) throws Exception { 23 | http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) 24 | .and().requestMatchers().anyRequest() 25 | .and().anonymous() 26 | .and().authorizeRequests() 27 | // .antMatchers("/product/**").access("#oauth2.hasScope('select') and hasRole('ROLE_USER')") 28 | .antMatchers("/**").authenticated(); //配置访问权限控制,必须认证过后才可以访问 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SpringSecurityOauth2/src/main/java/oauth/security/client/configauto/ApplyClientDetailService.java: -------------------------------------------------------------------------------- 1 | package oauth.security.client.configauto; 2 | 3 | import org.apache.tomcat.jdbc.pool.DataSource; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.security.oauth2.provider.ClientDetails; 6 | import org.springframework.security.oauth2.provider.ClientDetailsService; 7 | import org.springframework.security.oauth2.provider.ClientRegistrationException; 8 | import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService; 9 | import oauth.security.client.service.ApplyService; 10 | 11 | public class ApplyClientDetailService implements ClientDetailsService { 12 | 13 | @Autowired 14 | private ApplyService applyService; 15 | 16 | @Autowired 17 | private DataSource dataSource; 18 | 19 | @Override 20 | public ClientDetails loadClientByClientId(String applyName) throws ClientRegistrationException { 21 | 22 | /* 23 | // 使用mybatic验证client是否存在 ,根据需求写sql 24 | Map clientMap = applyService.findApplyById(applyName); 25 | 26 | if(clientMap == null) { 27 | throw new ClientRegistrationException("应用" + applyName + "不存在!"); 28 | }*/ 29 | 30 | // MyJdbcClientDetailsService jdbcClientDetailsService= new MyJdbcClientDetailsService(dataSource, "authentication"); 31 | JdbcClientDetailsService jdbcClientDetailsService= new JdbcClientDetailsService(dataSource); 32 | ClientDetails clientDetails = jdbcClientDetailsService.loadClientByClientId(applyName); 33 | 34 | return clientDetails; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /SpringSecurityOauth2/src/main/java/oauth/security/client/domain/ApplyDetails.java: -------------------------------------------------------------------------------- 1 | package oauth.security.client.domain; 2 | 3 | import org.springframework.security.core.GrantedAuthority; 4 | import org.springframework.security.oauth2.provider.ClientDetails; 5 | 6 | 7 | import java.util.*; 8 | 9 | public class ApplyDetails implements ClientDetails{ 10 | 11 | private final String clientId; 12 | 13 | private final String secret; 14 | 15 | private final Set authorizedGrantTypes = new HashSet(){{ add("client_credentials"); add("refresh_token");}}; 16 | 17 | private final Set scope = new HashSet() {{add("all"); }}; 18 | 19 | private Collection authorities; 20 | 21 | 22 | public ApplyDetails(String clientId, String secret) { 23 | this.clientId = clientId; 24 | this.secret = secret; 25 | 26 | // this.authorities = authorities; 27 | 28 | System.out.println("adsad"); 29 | } 30 | 31 | public String getSecret() { 32 | return secret; 33 | } 34 | 35 | @Override 36 | public String getClientId() { 37 | return this.clientId; 38 | } 39 | 40 | @Override 41 | public Set getResourceIds() { 42 | return null; 43 | } 44 | 45 | @Override 46 | public boolean isSecretRequired() { 47 | return true; 48 | } 49 | 50 | @Override 51 | public String getClientSecret() { 52 | return this.secret; 53 | } 54 | 55 | @Override 56 | public boolean isScoped() { 57 | return true; 58 | } 59 | 60 | @Override 61 | public Set getScope() { 62 | return this.scope; 63 | } 64 | 65 | @Override 66 | public Set getAuthorizedGrantTypes() { 67 | return this.authorizedGrantTypes; 68 | } 69 | 70 | @Override 71 | public Set getRegisteredRedirectUri() { 72 | return null; 73 | } 74 | 75 | @Override 76 | public Collection getAuthorities() { 77 | return this.authorities; 78 | } 79 | 80 | @Override 81 | public Integer getAccessTokenValiditySeconds() { 82 | return null; 83 | } 84 | 85 | @Override 86 | public Integer getRefreshTokenValiditySeconds() { 87 | return null; 88 | } 89 | 90 | @Override 91 | public boolean isAutoApprove(String s) { 92 | return false; 93 | } 94 | 95 | @Override 96 | public Map getAdditionalInformation() { 97 | return null; 98 | } 99 | } 100 | 101 | -------------------------------------------------------------------------------- /SpringSecurityOauth2/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | oauth2-demo 8 | oauth2-demo 9 | 1.0 10 | jar 11 | 12 | 13 | org.springframework.boot 14 | spring-boot-starter-parent 15 | 1.5.4.RELEASE 16 | 17 | 18 | 19 | UTF-8 20 | UTF-8 21 | 1.8 22 | 2.3.3.RELEASE 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-security 28 | 29 | 30 | org.springframework.security.oauth 31 | spring-security-oauth2 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-web 36 | 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-data-redis 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-starter-actuator 45 | 46 | 47 | 48 | org.mybatis.spring.boot 49 | mybatis-spring-boot-starter 50 | 1.3.0 51 | 52 | 53 | 54 | mysql 55 | mysql-connector-java 56 | 57 | 58 | 59 | 60 | 61 | 62 | org.springframework.boot 63 | spring-boot-maven-plugin 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /Spring2.0SecurityOauth2/src/main/java/com/oauth/client/config/SecurityConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.oauth.client.config; 2 | 3 | 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.data.redis.connection.RedisConnectionFactory; 8 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 9 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 10 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 11 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 12 | import org.springframework.security.core.userdetails.User; 13 | import org.springframework.security.core.userdetails.UserDetailsService; 14 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 15 | import org.springframework.security.oauth2.provider.ClientDetailsService; 16 | import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler; 17 | import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; 18 | import org.springframework.security.oauth2.provider.token.TokenStore; 19 | import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore; 20 | import org.springframework.security.provisioning.InMemoryUserDetailsManager; 21 | 22 | /** 23 | * Created by fcz on 2017/12/28. 24 | */ 25 | @Configuration 26 | @EnableWebSecurity 27 | public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 28 | 29 | @Bean 30 | @Override 31 | protected UserDetailsService userDetailsService(){ 32 | InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(); 33 | manager.createUser(User.withUsername("user_1").password(new BCryptPasswordEncoder().encode("123456")).authorities("USER").build()); 34 | manager.createUser(User.withUsername("user_2").password(new BCryptPasswordEncoder().encode("123456")).authorities("USER").build()); 35 | return manager; 36 | } 37 | 38 | @Override 39 | protected void configure(HttpSecurity http) throws Exception { 40 | http 41 | .requestMatchers().anyRequest() 42 | .and().authorizeRequests().antMatchers("/oauth/*").permitAll(); 43 | } 44 | 45 | // 使用 用户登录的加密策略 46 | /* protected void configure(AuthenticationManagerBuilder auth) throws Exception { 47 | //inMemoryAuthentication 从内存中获取 48 | auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) 49 | .withUser("user1") 50 | .password(new BCryptPasswordEncoder().encode("123456")).roles("USER"); 51 | }*/ 52 | 53 | } 54 | -------------------------------------------------------------------------------- /Spring2.0SecurityOauth2/src/main/java/com/oauth/client/config/AuthorizationServerConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.oauth.client.config; 2 | 3 | 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.data.redis.connection.RedisConnectionFactory; 7 | import org.springframework.security.authentication.AuthenticationManager; 8 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 9 | import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; 10 | import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; 11 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; 12 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; 13 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; 14 | import org.springframework.security.oauth2.provider.token.TokenStore; 15 | 16 | 17 | @Configuration 18 | @EnableAuthorizationServer 19 | public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { 20 | 21 | private static final String DEMO_RESOURCE_ID = "*"; 22 | 23 | @Autowired(required = false) 24 | AuthenticationManager authenticationManager; 25 | 26 | @Autowired 27 | RedisConnectionFactory redisConnectionFactory; 28 | 29 | @Autowired 30 | private TokenStore getRedisTokenStore() { 31 | return new MyRedisTokenStore(redisConnectionFactory); 32 | } 33 | /** 34 | * 配置客户端, 用于client认证 35 | * 使用存在内存中配置 s 36 | * pring2.0 密码规则改了 需要{id}password 格式,id为密码类型 这里使用bcrypt加密 37 | * 加密类型可以查看 38 | * @see org.springframework.security.crypto.password.PasswordEncoderUtils 39 | */ 40 | @Override 41 | public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 42 | clients.inMemory() 43 | .withClient("client_1") 44 | .resourceIds(DEMO_RESOURCE_ID) 45 | .authorizedGrantTypes("client_credentials", "refresh_token") 46 | .scopes("all") 47 | .authorities("client") 48 | .secret("{bcrypt}" + new BCryptPasswordEncoder().encode("123456")); 49 | } 50 | 51 | @Override 52 | public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 53 | endpoints.tokenStore(getRedisTokenStore()) // 使用自定义Redis token,新版的redis去除了set方法 54 | .authenticationManager(authenticationManager); 55 | } 56 | 57 | @Override 58 | public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { 59 | //允许表单认证 60 | oauthServer.allowFormAuthenticationForClients(); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /Spring2.0SecurityOauth2/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | oauth2-demo 8 | oauth2-demo 9 | 1.0 10 | jar 11 | 12 | 13 | org.springframework.boot 14 | spring-boot-starter-parent 15 | 2.0.5.RELEASE 16 | 17 | 18 | 19 | UTF-8 20 | UTF-8 21 | 1.8 22 | 2.3.3.RELEASE 23 | 24 | 25 | 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-web 30 | 31 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-security 39 | 40 | 41 | 46 | 47 | org.springframework.security.oauth.boot 48 | spring-security-oauth2-autoconfigure 49 | 2.0.0.RELEASE 50 | 51 | 52 | 53 | 54 | org.springframework.boot 55 | spring-boot-starter-data-redis 56 | 57 | 58 | 62 | 63 | 64 | 65 | 66 | 67 | org.springframework.boot 68 | spring-boot-maven-plugin 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /SpringSecurityOauth2/src/main/java/oauth/security/client/configauto/SecurityConfiguration.java: -------------------------------------------------------------------------------- 1 | package oauth.security.client.configauto; 2 | 3 | 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.data.redis.connection.RedisConnectionFactory; 8 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 10 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 11 | import org.springframework.security.core.userdetails.User; 12 | import org.springframework.security.core.userdetails.UserDetailsService; 13 | import org.springframework.security.oauth2.provider.ClientDetailsService; 14 | import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler; 15 | import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; 16 | import org.springframework.security.oauth2.provider.token.TokenStore; 17 | import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore; 18 | import org.springframework.security.provisioning.InMemoryUserDetailsManager; 19 | 20 | /** 21 | * Created by fcz on 2017/12/28. 22 | */ 23 | @Configuration 24 | @EnableWebSecurity 25 | public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 26 | 27 | @Autowired 28 | private ClientDetailsService clientDetailsService; 29 | 30 | @Autowired 31 | private RedisConnectionFactory redisConnection; 32 | 33 | @Bean // 声明ApplyClientDetailService 34 | public ApplyClientDetailService getClientDetails() { 35 | return new ApplyClientDetailService(); 36 | } 37 | 38 | @Bean 39 | @Override 40 | protected UserDetailsService userDetailsService(){ 41 | InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(); 42 | manager.createUser(User.withUsername("user_1").password("123456").authorities("USER").build()); 43 | manager.createUser(User.withUsername("user_2").password("123456").authorities("USER").build()); 44 | return manager; 45 | } 46 | 47 | @Bean 48 | public TokenStore tokenStore() { 49 | return new RedisTokenStore(redisConnection); 50 | } 51 | 52 | @Bean 53 | @Autowired 54 | public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){ 55 | TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler(); 56 | handler.setTokenStore(tokenStore()); 57 | handler.setRequestFactory(new DefaultOAuth2RequestFactory(getClientDetails())); 58 | handler.setClientDetailsService(getClientDetails()); 59 | return handler; 60 | } 61 | 62 | @Override 63 | protected void configure(HttpSecurity http) throws Exception { 64 | http 65 | .requestMatchers().anyRequest() 66 | .and().authorizeRequests().antMatchers("/oauth/*").permitAll(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /SpringSecurityOauth2/src/main/java/oauth/security/client/configauto/AuthorizationServerConfiguration.java: -------------------------------------------------------------------------------- 1 | package oauth.security.client.configauto; 2 | 3 | 4 | import org.apache.tomcat.jdbc.pool.DataSource; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.data.redis.connection.RedisConnectionFactory; 9 | import org.springframework.security.authentication.AuthenticationManager; 10 | import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; 11 | import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; 12 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; 13 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; 14 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; 15 | 16 | import org.springframework.security.oauth2.provider.token.TokenStore; 17 | import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; 18 | import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore; 19 | import oauth.security.client.configauto.jdbcdetail.MyJdbcTokenStore; 20 | 21 | @Configuration 22 | @EnableAuthorizationServer 23 | public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { 24 | 25 | private static final String DEMO_RESOURCE_ID = "*"; 26 | 27 | @Autowired 28 | AuthenticationManager authenticationManager; 29 | 30 | @Autowired 31 | RedisConnectionFactory redisConnectionFactory; 32 | 33 | @Autowired 34 | private DataSource dataSource; 35 | 36 | // 初始化JdbcTokenStore 37 | @Autowired 38 | public TokenStore getTokenStore() { 39 | return new JdbcTokenStore(dataSource); 40 | } 41 | 42 | // 自定义数据库存储tokenStore 43 | @Autowired 44 | public TokenStore getMyTokenStore() { 45 | return new MyJdbcTokenStore(dataSource); 46 | } 47 | 48 | @Autowired 49 | private TokenStore getRedisTokenStore() { 50 | return new RedisTokenStore(redisConnectionFactory); 51 | } 52 | 53 | @Bean // 声明ApplyClientDetailService 54 | public ApplyClientDetailService getClientDetails() { 55 | return new ApplyClientDetailService(); 56 | } 57 | 58 | @Override 59 | public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 60 | // 配置客户端, 用于client认证 61 | clients.withClientDetails(getClientDetails()); 62 | /* //使用存在内存中配置 63 | clients.inMemory().withClient("client_1") 64 | .resourceIds(DEMO_RESOURCE_ID) 65 | .authorizedGrantTypes("client_credentials", "refresh_token") 66 | .scopes("all") 67 | .authorities("client") 68 | .secret("123456");*/ 69 | } 70 | 71 | @Override 72 | public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 73 | endpoints.tokenStore(new RedisTokenStore(redisConnectionFactory)) 74 | .authenticationManager(authenticationManager); // redis保存token 75 | /* endpoints.tokenStore(getTokenStore()) // 数据库保存token 76 | .authenticationManager(authenticationManager);*/ 77 | } 78 | 79 | @Override 80 | public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { 81 | //允许表单认证 82 | oauthServer.allowFormAuthenticationForClients(); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /SpringSecurityOauth2/src/main/java/oauth/security/client/configauto/jdbcdetail/MyJdbcClientDetailsService.java: -------------------------------------------------------------------------------- 1 | package oauth.security.client.configauto.jdbcdetail; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import org.apache.commons.logging.Log; 5 | import org.apache.commons.logging.LogFactory; 6 | import org.springframework.dao.DuplicateKeyException; 7 | import org.springframework.dao.EmptyResultDataAccessException; 8 | import org.springframework.jdbc.core.JdbcTemplate; 9 | import org.springframework.jdbc.core.RowMapper; 10 | import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; 11 | import org.springframework.security.crypto.password.NoOpPasswordEncoder; 12 | import org.springframework.security.crypto.password.PasswordEncoder; 13 | import org.springframework.security.oauth2.common.exceptions.InvalidClientException; 14 | import org.springframework.security.oauth2.common.util.DefaultJdbcListFactory; 15 | import org.springframework.security.oauth2.common.util.JdbcListFactory; 16 | import org.springframework.security.oauth2.provider.client.BaseClientDetails; 17 | import org.springframework.util.Assert; 18 | import org.springframework.util.ClassUtils; 19 | import org.springframework.util.StringUtils; 20 | 21 | import javax.sql.DataSource; 22 | import java.sql.ResultSet; 23 | import java.sql.SQLException; 24 | import java.util.Collections; 25 | import java.util.HashSet; 26 | import java.util.Iterator; 27 | import java.util.List; 28 | import java.util.Map; 29 | import java.util.Set; 30 | 31 | import org.springframework.security.oauth2.provider.ClientAlreadyExistsException; 32 | import org.springframework.security.oauth2.provider.ClientDetails; 33 | import org.springframework.security.oauth2.provider.ClientDetailsService; 34 | import org.springframework.security.oauth2.provider.ClientRegistrationService; 35 | import org.springframework.security.oauth2.provider.NoSuchClientException; 36 | 37 | public class MyJdbcClientDetailsService implements ClientDetailsService, ClientRegistrationService { 38 | private static final Log logger = LogFactory.getLog(org.springframework.security.oauth2.provider.client.JdbcClientDetailsService.class); 39 | private JsonMapper mapper = createJsonMapper(); 40 | private static final String CLIENT_FIELDS_FOR_UPDATE = "resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove"; 41 | private static final String CLIENT_FIELDS = "client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove"; 42 | private static final String BASE_FIND_STATEMENT = "select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details"; 43 | private static final String DEFAULT_FIND_STATEMENT = "select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details order by client_id"; 44 | private static final String DEFAULT_SELECT_STATEMENT = "select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details where client_id = ?"; 45 | private static final String DEFAULT_INSERT_STATEMENT = "insert into oauth_client_details (client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove, client_id) values (?,?,?,?,?,?,?,?,?,?,?)"; 46 | private static final String DEFAULT_UPDATE_STATEMENT = "update oauth_client_details set " + "resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove".replaceAll(", ", "=?, ") + "=? where client_id = ?"; 47 | private static final String DEFAULT_UPDATE_SECRET_STATEMENT = "update oauth_client_details set client_secret = ? where client_id = ?"; 48 | private static final String DEFAULT_DELETE_STATEMENT = "delete from oauth_client_details where client_id = ?"; 49 | private RowMapper rowMapper = new ClientDetailsRowMapper(); 50 | private String deleteClientDetailsSql = "delete from oauth_client_details where client_id = ?"; 51 | private String findClientDetailsSql = "select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details order by client_id"; 52 | private String updateClientDetailsSql; 53 | private String updateClientSecretSql; 54 | private String insertClientDetailsSql; 55 | private String selectClientDetailsSql; 56 | private PasswordEncoder passwordEncoder; 57 | private final JdbcTemplate jdbcTemplate; 58 | private JdbcListFactory listFactory; 59 | 60 | public MyJdbcClientDetailsService(DataSource dataSource) { 61 | this.updateClientDetailsSql = DEFAULT_UPDATE_STATEMENT; 62 | this.updateClientSecretSql = "update oauth_client_details set client_secret = ? where client_id = ?"; 63 | this.insertClientDetailsSql = "insert into oauth_client_details (client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove, client_id) values (?,?,?,?,?,?,?,?,?,?,?)"; 64 | this.selectClientDetailsSql = "select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details where client_id = ?"; 65 | this.passwordEncoder = NoOpPasswordEncoder.getInstance(); 66 | Assert.notNull(dataSource, "DataSource required"); 67 | this.jdbcTemplate = new JdbcTemplate(dataSource); 68 | this.listFactory = new DefaultJdbcListFactory(new NamedParameterJdbcTemplate(this.jdbcTemplate)); 69 | } 70 | 71 | public MyJdbcClientDetailsService(DataSource dataSource, String dataTableName) { 72 | this.updateClientDetailsSql = DEFAULT_UPDATE_STATEMENT; 73 | this.updateClientSecretSql = "update " + dataTableName + " set client_secret = ? where client_id = ?"; 74 | this.insertClientDetailsSql = "insert into " + dataTableName +" (client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove, client_id) values (?,?,?,?,?,?,?,?,?,?,?)"; 75 | this.selectClientDetailsSql = "select client_name AS client_id, client_secret, resource_ids, scope, authorized_grant_types, null AS web_server_redirect_uri, authorities, null AS access_token_validity, null AS refresh_token_validity, null AS additional_information, null AS autoapprove from " + dataTableName + " where client_name = ?"; 76 | this.passwordEncoder = NoOpPasswordEncoder.getInstance(); 77 | Assert.notNull(dataSource, "DataSource required"); 78 | this.jdbcTemplate = new JdbcTemplate(dataSource); 79 | this.listFactory = new DefaultJdbcListFactory(new NamedParameterJdbcTemplate(this.jdbcTemplate)); 80 | } 81 | 82 | public void setPasswordEncoder(PasswordEncoder passwordEncoder) { 83 | this.passwordEncoder = passwordEncoder; 84 | } 85 | 86 | public ClientDetails loadClientByClientId(String clientId) throws InvalidClientException { 87 | try { 88 | ClientDetails details = (ClientDetails)this.jdbcTemplate.queryForObject(this.selectClientDetailsSql, new ClientDetailsRowMapper(), new Object[]{clientId}); 89 | return details; 90 | } catch (EmptyResultDataAccessException var4) { 91 | throw new NoSuchClientException("No client with requested id: " + clientId); 92 | } 93 | } 94 | 95 | public void addClientDetails(ClientDetails clientDetails) throws ClientAlreadyExistsException { 96 | try { 97 | this.jdbcTemplate.update(this.insertClientDetailsSql, this.getFields(clientDetails)); 98 | } catch (DuplicateKeyException var3) { 99 | throw new ClientAlreadyExistsException("Client already exists: " + clientDetails.getClientId(), var3); 100 | } 101 | } 102 | 103 | public void updateClientDetails(ClientDetails clientDetails) throws NoSuchClientException { 104 | int count = this.jdbcTemplate.update(this.updateClientDetailsSql, this.getFieldsForUpdate(clientDetails)); 105 | if (count != 1) { 106 | throw new NoSuchClientException("No client found with id = " + clientDetails.getClientId()); 107 | } 108 | } 109 | 110 | public void updateClientSecret(String clientId, String secret) throws NoSuchClientException { 111 | int count = this.jdbcTemplate.update(this.updateClientSecretSql, new Object[]{this.passwordEncoder.encode(secret), clientId}); 112 | if (count != 1) { 113 | throw new NoSuchClientException("No client found with id = " + clientId); 114 | } 115 | } 116 | 117 | public void removeClientDetails(String clientId) throws NoSuchClientException { 118 | int count = this.jdbcTemplate.update(this.deleteClientDetailsSql, new Object[]{clientId}); 119 | if (count != 1) { 120 | throw new NoSuchClientException("No client found with id = " + clientId); 121 | } 122 | } 123 | 124 | public List listClientDetails() { 125 | return this.listFactory.getList(this.findClientDetailsSql, Collections.emptyMap(), this.rowMapper); 126 | } 127 | 128 | private Object[] getFields(ClientDetails clientDetails) { 129 | Object[] fieldsForUpdate = this.getFieldsForUpdate(clientDetails); 130 | Object[] fields = new Object[fieldsForUpdate.length + 1]; 131 | System.arraycopy(fieldsForUpdate, 0, fields, 1, fieldsForUpdate.length); 132 | fields[0] = clientDetails.getClientSecret() != null ? this.passwordEncoder.encode(clientDetails.getClientSecret()) : null; 133 | return fields; 134 | } 135 | 136 | private Object[] getFieldsForUpdate(ClientDetails clientDetails) { 137 | String json = null; 138 | 139 | try { 140 | json = this.mapper.write(clientDetails.getAdditionalInformation()); 141 | } catch (Exception var4) { 142 | logger.warn("Could not serialize additional information: " + clientDetails, var4); 143 | } 144 | 145 | return new Object[]{clientDetails.getResourceIds() != null ? StringUtils.collectionToCommaDelimitedString(clientDetails.getResourceIds()) : null, clientDetails.getScope() != null ? StringUtils.collectionToCommaDelimitedString(clientDetails.getScope()) : null, clientDetails.getAuthorizedGrantTypes() != null ? StringUtils.collectionToCommaDelimitedString(clientDetails.getAuthorizedGrantTypes()) : null, clientDetails.getRegisteredRedirectUri() != null ? StringUtils.collectionToCommaDelimitedString(clientDetails.getRegisteredRedirectUri()) : null, clientDetails.getAuthorities() != null ? StringUtils.collectionToCommaDelimitedString(clientDetails.getAuthorities()) : null, clientDetails.getAccessTokenValiditySeconds(), clientDetails.getRefreshTokenValiditySeconds(), json, this.getAutoApproveScopes(clientDetails), clientDetails.getClientId()}; 146 | } 147 | 148 | private String getAutoApproveScopes(ClientDetails clientDetails) { 149 | if (clientDetails.isAutoApprove("true")) { 150 | return "true"; 151 | } else { 152 | Set scopes = new HashSet(); 153 | Iterator var3 = clientDetails.getScope().iterator(); 154 | 155 | while(var3.hasNext()) { 156 | String scope = (String)var3.next(); 157 | if (clientDetails.isAutoApprove(scope)) { 158 | scopes.add(scope); 159 | } 160 | } 161 | 162 | return StringUtils.collectionToCommaDelimitedString(scopes); 163 | } 164 | } 165 | 166 | public void setSelectClientDetailsSql(String selectClientDetailsSql) { 167 | this.selectClientDetailsSql = selectClientDetailsSql; 168 | } 169 | 170 | public void setDeleteClientDetailsSql(String deleteClientDetailsSql) { 171 | this.deleteClientDetailsSql = deleteClientDetailsSql; 172 | } 173 | 174 | public void setUpdateClientDetailsSql(String updateClientDetailsSql) { 175 | this.updateClientDetailsSql = updateClientDetailsSql; 176 | } 177 | 178 | public void setUpdateClientSecretSql(String updateClientSecretSql) { 179 | this.updateClientSecretSql = updateClientSecretSql; 180 | } 181 | 182 | public void setInsertClientDetailsSql(String insertClientDetailsSql) { 183 | this.insertClientDetailsSql = insertClientDetailsSql; 184 | } 185 | 186 | public void setFindClientDetailsSql(String findClientDetailsSql) { 187 | this.findClientDetailsSql = findClientDetailsSql; 188 | } 189 | 190 | public void setListFactory(JdbcListFactory listFactory) { 191 | this.listFactory = listFactory; 192 | } 193 | 194 | public void setRowMapper(RowMapper rowMapper) { 195 | this.rowMapper = rowMapper; 196 | } 197 | 198 | private static JsonMapper createJsonMapper() { 199 | if (ClassUtils.isPresent("org.codehaus.jackson.map.ObjectMapper", (ClassLoader)null)) { 200 | return new JacksonMapper(); 201 | } else { 202 | return (JsonMapper)(ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", (ClassLoader)null) ? new Jackson2Mapper() : new NotSupportedJsonMapper()); 203 | } 204 | } 205 | 206 | private static class NotSupportedJsonMapper implements JsonMapper { 207 | private NotSupportedJsonMapper() { 208 | } 209 | 210 | public String write(Object input) throws Exception { 211 | throw new UnsupportedOperationException("Neither Jackson 1 nor 2 is available so JSON conversion cannot be done"); 212 | } 213 | 214 | public T read(String input, Class type) throws Exception { 215 | throw new UnsupportedOperationException("Neither Jackson 1 nor 2 is available so JSON conversion cannot be done"); 216 | } 217 | } 218 | 219 | private static class Jackson2Mapper implements JsonMapper { 220 | private ObjectMapper mapper; 221 | 222 | private Jackson2Mapper() { 223 | this.mapper = new ObjectMapper(); 224 | } 225 | 226 | public String write(Object input) throws Exception { 227 | return this.mapper.writeValueAsString(input); 228 | } 229 | 230 | public T read(String input, Class type) throws Exception { 231 | return this.mapper.readValue(input, type); 232 | } 233 | } 234 | 235 | private static class JacksonMapper implements JsonMapper { 236 | private org.codehaus.jackson.map.ObjectMapper mapper; 237 | 238 | private JacksonMapper() { 239 | this.mapper = new org.codehaus.jackson.map.ObjectMapper(); 240 | } 241 | 242 | public String write(Object input) throws Exception { 243 | return this.mapper.writeValueAsString(input); 244 | } 245 | 246 | public T read(String input, Class type) throws Exception { 247 | return this.mapper.readValue(input, type); 248 | } 249 | } 250 | 251 | interface JsonMapper { 252 | String write(Object var1) throws Exception; 253 | 254 | T read(String var1, Class var2) throws Exception; 255 | } 256 | 257 | private static class ClientDetailsRowMapper implements RowMapper { 258 | private JsonMapper mapper; 259 | 260 | private ClientDetailsRowMapper() { 261 | this.mapper = MyJdbcClientDetailsService.createJsonMapper(); 262 | } 263 | 264 | public ClientDetails mapRow(ResultSet rs, int rowNum) throws SQLException { 265 | BaseClientDetails details = new BaseClientDetails(rs.getString(1), rs.getString(3), rs.getString(4), rs.getString(5), rs.getString(7), rs.getString(6)); 266 | details.setClientSecret(rs.getString(2)); 267 | if (rs.getObject(8) != null) { 268 | details.setAccessTokenValiditySeconds(rs.getInt(8)); 269 | } 270 | 271 | if (rs.getObject(9) != null) { 272 | details.setRefreshTokenValiditySeconds(rs.getInt(9)); 273 | } 274 | 275 | String json = rs.getString(10); 276 | if (json != null) { 277 | try { 278 | Map additionalInformation = (Map)this.mapper.read(json, Map.class); 279 | details.setAdditionalInformation(additionalInformation); 280 | } catch (Exception var6) { 281 | MyJdbcClientDetailsService.logger.warn("Could not decode JSON for additional information: " + details, var6); 282 | } 283 | } 284 | 285 | String scopes = rs.getString(11); 286 | if (scopes != null) { 287 | details.setAutoApproveScopes(StringUtils.commaDelimitedListToSet(scopes)); 288 | } 289 | 290 | return details; 291 | } 292 | } 293 | } 294 | 295 | -------------------------------------------------------------------------------- /Spring2.0SecurityOauth2/src/main/java/com/oauth/client/config/MyRedisTokenStore.java: -------------------------------------------------------------------------------- 1 | package com.oauth.client.config; 2 | import java.util.ArrayList; 3 | import java.util.Collection; 4 | import java.util.Collections; 5 | import java.util.Date; 6 | import java.util.List; 7 | import org.springframework.data.redis.connection.RedisConnection; 8 | import org.springframework.data.redis.connection.RedisConnectionFactory; 9 | import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; 10 | import org.springframework.security.oauth2.common.OAuth2AccessToken; 11 | import org.springframework.security.oauth2.common.OAuth2RefreshToken; 12 | import org.springframework.security.oauth2.provider.OAuth2Authentication; 13 | import org.springframework.security.oauth2.provider.token.AuthenticationKeyGenerator; 14 | import org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator; 15 | import org.springframework.security.oauth2.provider.token.TokenStore; 16 | import org.springframework.security.oauth2.provider.token.store.redis.JdkSerializationStrategy; 17 | import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStoreSerializationStrategy; 18 | import org.springframework.stereotype.Component; 19 | 20 | 21 | @Component 22 | public class MyRedisTokenStore implements TokenStore { 23 | private static final String ACCESS = "access:"; 24 | private static final String AUTH_TO_ACCESS = "auth_to_access:"; 25 | private static final String AUTH = "auth:"; 26 | private static final String REFRESH_AUTH = "refresh_auth:"; 27 | private static final String ACCESS_TO_REFRESH = "access_to_refresh:"; 28 | private static final String REFRESH = "refresh:"; 29 | private static final String REFRESH_TO_ACCESS = "refresh_to_access:"; 30 | private static final String CLIENT_ID_TO_ACCESS = "client_id_to_access:"; 31 | private static final String UNAME_TO_ACCESS = "uname_to_access:"; 32 | private final RedisConnectionFactory connectionFactory; 33 | private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator(); 34 | private RedisTokenStoreSerializationStrategy serializationStrategy = new JdkSerializationStrategy(); 35 | private String prefix = ""; 36 | 37 | public MyRedisTokenStore(RedisConnectionFactory connectionFactory) { 38 | this.connectionFactory = connectionFactory; 39 | } 40 | 41 | public void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) { 42 | this.authenticationKeyGenerator = authenticationKeyGenerator; 43 | } 44 | 45 | public void setSerializationStrategy(RedisTokenStoreSerializationStrategy serializationStrategy) { 46 | this.serializationStrategy = serializationStrategy; 47 | } 48 | 49 | public void setPrefix(String prefix) { 50 | this.prefix = prefix; 51 | } 52 | 53 | private RedisConnection getConnection() { 54 | return this.connectionFactory.getConnection(); 55 | } 56 | 57 | private byte[] serialize(Object object) { 58 | return this.serializationStrategy.serialize(object); 59 | } 60 | 61 | private byte[] serializeKey(String object) { 62 | return this.serialize(this.prefix + object); 63 | } 64 | 65 | private OAuth2AccessToken deserializeAccessToken(byte[] bytes) { 66 | return (OAuth2AccessToken)this.serializationStrategy.deserialize(bytes, OAuth2AccessToken.class); 67 | } 68 | 69 | private OAuth2Authentication deserializeAuthentication(byte[] bytes) { 70 | return (OAuth2Authentication)this.serializationStrategy.deserialize(bytes, OAuth2Authentication.class); 71 | } 72 | 73 | private OAuth2RefreshToken deserializeRefreshToken(byte[] bytes) { 74 | return (OAuth2RefreshToken)this.serializationStrategy.deserialize(bytes, OAuth2RefreshToken.class); 75 | } 76 | 77 | private byte[] serialize(String string) { 78 | return this.serializationStrategy.serialize(string); 79 | } 80 | 81 | private String deserializeString(byte[] bytes) { 82 | return this.serializationStrategy.deserializeString(bytes); 83 | } 84 | 85 | @Override 86 | public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { 87 | String key = this.authenticationKeyGenerator.extractKey(authentication); 88 | byte[] serializedKey = this.serializeKey(AUTH_TO_ACCESS + key); 89 | byte[] bytes = null; 90 | RedisConnection conn = this.getConnection(); 91 | try { 92 | bytes = conn.get(serializedKey); 93 | } finally { 94 | conn.close(); 95 | } 96 | OAuth2AccessToken accessToken = this.deserializeAccessToken(bytes); 97 | if (accessToken != null) { 98 | OAuth2Authentication storedAuthentication = this.readAuthentication(accessToken.getValue()); 99 | if (storedAuthentication == null || !key.equals(this.authenticationKeyGenerator.extractKey(storedAuthentication))) { 100 | this.storeAccessToken(accessToken, authentication); 101 | } 102 | } 103 | return accessToken; 104 | } 105 | 106 | @Override 107 | public OAuth2Authentication readAuthentication(OAuth2AccessToken token) { 108 | return this.readAuthentication(token.getValue()); 109 | } 110 | 111 | @Override 112 | public OAuth2Authentication readAuthentication(String token) { 113 | byte[] bytes = null; 114 | RedisConnection conn = this.getConnection(); 115 | try { 116 | bytes = conn.get(this.serializeKey("auth:" + token)); 117 | } finally { 118 | conn.close(); 119 | } 120 | OAuth2Authentication auth = this.deserializeAuthentication(bytes); 121 | return auth; 122 | } 123 | 124 | @Override 125 | public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) { 126 | return this.readAuthenticationForRefreshToken(token.getValue()); 127 | } 128 | 129 | public OAuth2Authentication readAuthenticationForRefreshToken(String token) { 130 | RedisConnection conn = getConnection(); 131 | try { 132 | byte[] bytes = conn.get(serializeKey(REFRESH_AUTH + token)); 133 | OAuth2Authentication auth = deserializeAuthentication(bytes); 134 | return auth; 135 | } finally { 136 | conn.close(); 137 | } 138 | } 139 | 140 | @Override 141 | public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { 142 | byte[] serializedAccessToken = serialize(token); 143 | byte[] serializedAuth = serialize(authentication); 144 | byte[] accessKey = serializeKey(ACCESS + token.getValue()); 145 | byte[] authKey = serializeKey(AUTH + token.getValue()); 146 | byte[] authToAccessKey = serializeKey(AUTH_TO_ACCESS + authenticationKeyGenerator.extractKey(authentication)); 147 | byte[] approvalKey = serializeKey(UNAME_TO_ACCESS + getApprovalKey(authentication)); 148 | byte[] clientId = serializeKey(CLIENT_ID_TO_ACCESS + authentication.getOAuth2Request().getClientId()); 149 | 150 | RedisConnection conn = getConnection(); 151 | try { 152 | conn.openPipeline(); 153 | conn.stringCommands().set(accessKey, serializedAccessToken); 154 | conn.stringCommands().set(authKey, serializedAuth); 155 | conn.stringCommands().set(authToAccessKey, serializedAccessToken); 156 | if (!authentication.isClientOnly()) { 157 | conn.rPush(approvalKey, serializedAccessToken); 158 | } 159 | conn.rPush(clientId, serializedAccessToken); 160 | if (token.getExpiration() != null) { 161 | int seconds = token.getExpiresIn(); 162 | conn.expire(accessKey, seconds); 163 | conn.expire(authKey, seconds); 164 | conn.expire(authToAccessKey, seconds); 165 | conn.expire(clientId, seconds); 166 | conn.expire(approvalKey, seconds); 167 | } 168 | OAuth2RefreshToken refreshToken = token.getRefreshToken(); 169 | if (refreshToken != null && refreshToken.getValue() != null) { 170 | byte[] refresh = serialize(token.getRefreshToken().getValue()); 171 | byte[] auth = serialize(token.getValue()); 172 | byte[] refreshToAccessKey = serializeKey(REFRESH_TO_ACCESS + token.getRefreshToken().getValue()); 173 | conn.stringCommands().set(refreshToAccessKey, auth); 174 | byte[] accessToRefreshKey = serializeKey(ACCESS_TO_REFRESH + token.getValue()); 175 | conn.stringCommands().set(accessToRefreshKey, refresh); 176 | if (refreshToken instanceof ExpiringOAuth2RefreshToken) { 177 | ExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken) refreshToken; 178 | Date expiration = expiringRefreshToken.getExpiration(); 179 | if (expiration != null) { 180 | int seconds = Long.valueOf((expiration.getTime() - System.currentTimeMillis()) / 1000L) 181 | .intValue(); 182 | conn.expire(refreshToAccessKey, seconds); 183 | conn.expire(accessToRefreshKey, seconds); 184 | } 185 | } 186 | } 187 | conn.closePipeline(); 188 | } finally { 189 | conn.close(); 190 | } 191 | } 192 | 193 | private static String getApprovalKey(OAuth2Authentication authentication) { 194 | String userName = authentication.getUserAuthentication() == null ? "": authentication.getUserAuthentication().getName(); 195 | return getApprovalKey(authentication.getOAuth2Request().getClientId(), userName); 196 | } 197 | 198 | private static String getApprovalKey(String clientId, String userName) { 199 | return clientId + (userName == null ? "" : ":" + userName); 200 | } 201 | 202 | @Override 203 | public void removeAccessToken(OAuth2AccessToken accessToken) { 204 | this.removeAccessToken(accessToken.getValue()); 205 | } 206 | 207 | @Override 208 | public OAuth2AccessToken readAccessToken(String tokenValue) { 209 | byte[] key = serializeKey(ACCESS + tokenValue); 210 | byte[] bytes = null; 211 | RedisConnection conn = getConnection(); 212 | try { 213 | bytes = conn.get(key); 214 | } finally { 215 | conn.close(); 216 | } 217 | OAuth2AccessToken accessToken = deserializeAccessToken(bytes); 218 | return accessToken; 219 | } 220 | 221 | public void removeAccessToken(String tokenValue) { 222 | byte[] accessKey = serializeKey(ACCESS + tokenValue); 223 | byte[] authKey = serializeKey(AUTH + tokenValue); 224 | byte[] accessToRefreshKey = serializeKey(ACCESS_TO_REFRESH + tokenValue); 225 | RedisConnection conn = getConnection(); 226 | try { 227 | conn.openPipeline(); 228 | conn.get(accessKey); 229 | conn.get(authKey); 230 | conn.del(accessKey); 231 | conn.del(accessToRefreshKey); 232 | // Don't remove the refresh token - it's up to the caller to do that 233 | conn.del(authKey); 234 | List results = conn.closePipeline(); 235 | byte[] access = (byte[]) results.get(0); 236 | byte[] auth = (byte[]) results.get(1); 237 | 238 | OAuth2Authentication authentication = deserializeAuthentication(auth); 239 | if (authentication != null) { 240 | String key = authenticationKeyGenerator.extractKey(authentication); 241 | byte[] authToAccessKey = serializeKey(AUTH_TO_ACCESS + key); 242 | byte[] unameKey = serializeKey(UNAME_TO_ACCESS + getApprovalKey(authentication)); 243 | byte[] clientId = serializeKey(CLIENT_ID_TO_ACCESS + authentication.getOAuth2Request().getClientId()); 244 | conn.openPipeline(); 245 | conn.del(authToAccessKey); 246 | conn.lRem(unameKey, 1, access); 247 | conn.lRem(clientId, 1, access); 248 | conn.del(serialize(ACCESS + key)); 249 | conn.closePipeline(); 250 | } 251 | } finally { 252 | conn.close(); 253 | } 254 | } 255 | 256 | @Override 257 | public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) { 258 | byte[] refreshKey = serializeKey(REFRESH + refreshToken.getValue()); 259 | byte[] refreshAuthKey = serializeKey(REFRESH_AUTH + refreshToken.getValue()); 260 | byte[] serializedRefreshToken = serialize(refreshToken); 261 | RedisConnection conn = getConnection(); 262 | try { 263 | conn.openPipeline(); 264 | conn.stringCommands().set(refreshKey, serializedRefreshToken); 265 | conn.stringCommands().set(refreshAuthKey, serialize(authentication)); 266 | if (refreshToken instanceof ExpiringOAuth2RefreshToken) { 267 | ExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken) refreshToken; 268 | Date expiration = expiringRefreshToken.getExpiration(); 269 | if (expiration != null) { 270 | int seconds = Long.valueOf((expiration.getTime() - System.currentTimeMillis()) / 1000L) 271 | .intValue(); 272 | conn.expire(refreshKey, seconds); 273 | conn.expire(refreshAuthKey, seconds); 274 | } 275 | } 276 | conn.closePipeline(); 277 | } finally { 278 | conn.close(); 279 | } 280 | } 281 | 282 | @Override 283 | public OAuth2RefreshToken readRefreshToken(String tokenValue) { 284 | byte[] key = serializeKey(REFRESH + tokenValue); 285 | byte[] bytes = null; 286 | RedisConnection conn = getConnection(); 287 | try { 288 | bytes = conn.get(key); 289 | } finally { 290 | conn.close(); 291 | } 292 | OAuth2RefreshToken refreshToken = deserializeRefreshToken(bytes); 293 | return refreshToken; 294 | } 295 | 296 | @Override 297 | public void removeRefreshToken(OAuth2RefreshToken refreshToken) { 298 | this.removeRefreshToken(refreshToken.getValue()); 299 | } 300 | 301 | public void removeRefreshToken(String tokenValue) { 302 | byte[] refreshKey = serializeKey(REFRESH + tokenValue); 303 | byte[] refreshAuthKey = serializeKey(REFRESH_AUTH + tokenValue); 304 | byte[] refresh2AccessKey = serializeKey(REFRESH_TO_ACCESS + tokenValue); 305 | byte[] access2RefreshKey = serializeKey(ACCESS_TO_REFRESH + tokenValue); 306 | RedisConnection conn = getConnection(); 307 | try { 308 | conn.openPipeline(); 309 | conn.del(refreshKey); 310 | conn.del(refreshAuthKey); 311 | conn.del(refresh2AccessKey); 312 | conn.del(access2RefreshKey); 313 | conn.closePipeline(); 314 | } finally { 315 | conn.close(); 316 | } 317 | } 318 | 319 | @Override 320 | public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) { 321 | this.removeAccessTokenUsingRefreshToken(refreshToken.getValue()); 322 | } 323 | 324 | private void removeAccessTokenUsingRefreshToken(String refreshToken) { 325 | byte[] key = serializeKey(REFRESH_TO_ACCESS + refreshToken); 326 | List results = null; 327 | RedisConnection conn = getConnection(); 328 | try { 329 | conn.openPipeline(); 330 | conn.get(key); 331 | conn.del(key); 332 | results = conn.closePipeline(); 333 | } finally { 334 | conn.close(); 335 | } 336 | if (results == null) { 337 | return; 338 | } 339 | byte[] bytes = (byte[]) results.get(0); 340 | String accessToken = deserializeString(bytes); 341 | if (accessToken != null) { 342 | removeAccessToken(accessToken); 343 | } 344 | } 345 | 346 | public Collection findTokensByClientIdAndUserName(String clientId, String userName) { 347 | byte[] approvalKey = serializeKey(UNAME_TO_ACCESS + getApprovalKey(clientId, userName)); 348 | List byteList = null; 349 | RedisConnection conn = getConnection(); 350 | try { 351 | byteList = conn.lRange(approvalKey, 0, -1); 352 | } finally { 353 | conn.close(); 354 | } 355 | if (byteList == null || byteList.size() == 0) { 356 | return Collections. emptySet(); 357 | } 358 | List accessTokens = new ArrayList(byteList.size()); 359 | for (byte[] bytes : byteList) { 360 | OAuth2AccessToken accessToken = deserializeAccessToken(bytes); 361 | accessTokens.add(accessToken); 362 | } 363 | return Collections. unmodifiableCollection(accessTokens); 364 | } 365 | 366 | @Override 367 | public Collection findTokensByClientId(String clientId) { 368 | byte[] key = serializeKey(CLIENT_ID_TO_ACCESS + clientId); 369 | List byteList = null; 370 | RedisConnection conn = getConnection(); 371 | try { 372 | byteList = conn.lRange(key, 0, -1); 373 | } finally { 374 | conn.close(); 375 | } 376 | if (byteList == null || byteList.size() == 0) { 377 | return Collections. emptySet(); 378 | } 379 | List accessTokens = new ArrayList(byteList.size()); 380 | for (byte[] bytes : byteList) { 381 | OAuth2AccessToken accessToken = deserializeAccessToken(bytes); 382 | accessTokens.add(accessToken); 383 | } 384 | return Collections. unmodifiableCollection(accessTokens); 385 | } 386 | 387 | } 388 | -------------------------------------------------------------------------------- /SpringSecurityOauth2/src/main/java/oauth/security/client/configauto/jdbcdetail/MyJdbcTokenStore.java: -------------------------------------------------------------------------------- 1 | package oauth.security.client.configauto.jdbcdetail; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | import org.springframework.dao.EmptyResultDataAccessException; 6 | import org.springframework.jdbc.core.JdbcTemplate; 7 | import org.springframework.jdbc.core.RowMapper; 8 | import org.springframework.jdbc.core.support.SqlLobValue; 9 | import org.springframework.security.oauth2.common.util.SerializationUtils; 10 | import org.springframework.security.oauth2.provider.ClientRegistrationException; 11 | import org.springframework.security.oauth2.provider.OAuth2Authentication; 12 | import org.springframework.security.oauth2.provider.token.AuthenticationKeyGenerator; 13 | import org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator; 14 | import org.springframework.security.oauth2.provider.token.TokenStore; 15 | import org.springframework.util.Assert; 16 | 17 | import javax.sql.DataSource; 18 | import java.io.UnsupportedEncodingException; 19 | import java.math.BigInteger; 20 | import java.security.MessageDigest; 21 | import java.security.NoSuchAlgorithmException; 22 | import java.sql.ResultSet; 23 | import java.sql.SQLException; 24 | import java.util.*; 25 | 26 | import org.springframework.security.oauth2.common.OAuth2AccessToken; 27 | import org.springframework.security.oauth2.common.OAuth2RefreshToken; 28 | 29 | /** 30 | * 自定义 jdbc TokenStore 31 | */ 32 | public class MyJdbcTokenStore implements TokenStore { 33 | private static final Log LOG = LogFactory.getLog(MyJdbcTokenStore.class); 34 | private String updateAccessTokenSql = "update authentication a set a.token_id = ?,a.token = ?,a.token_byte = ?, a.authentication_id = ?, a.authentication = ?, a.refresh_token = ? where id = ?"; 35 | private String selectExistClientFromClientNameSql = "select id from authentication where client_name = ? limit 1"; 36 | private String selectAccessTokenSql = "select token_id, token_byte from authentication where token_id = ?"; 37 | private String selectAccessTokenAuthenticationSql = "select token_id, authentication from authentication where token_id = ?"; 38 | private String selectAccessTokenFromAuthenticationSql = "select token_id, token_byte from authentication where authentication_id = ?"; 39 | // 下面SQL的没啥用 40 | private String selectAccessTokensFromClientIdSql = "select token_id, token from authentication where client_id = ?"; 41 | private String deleteAccessTokenSql = "delete from authentication where token_id = ?"; 42 | 43 | private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator(); 44 | private final JdbcTemplate jdbcTemplate; 45 | 46 | public MyJdbcTokenStore(DataSource dataSource) { 47 | Assert.notNull(dataSource, "DataSource required"); 48 | this.jdbcTemplate = new JdbcTemplate(dataSource); 49 | } 50 | 51 | public void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) { 52 | this.authenticationKeyGenerator = authenticationKeyGenerator; 53 | } 54 | 55 | /** 56 | * 判断token状态 获取token 57 | * @param authentication 58 | * @return 59 | */ 60 | public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { 61 | OAuth2AccessToken accessToken = null; 62 | String key = this.authenticationKeyGenerator.extractKey(authentication); //authentication_id 63 | 64 | //通过 authentication_id 查询 65 | try { 66 | accessToken = (OAuth2AccessToken)this.jdbcTemplate.queryForObject(this.selectAccessTokenFromAuthenticationSql, new RowMapper() { 67 | public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException { 68 | return MyJdbcTokenStore.this.deserializeAccessToken(rs.getBytes(2)); 69 | } 70 | }, new Object[]{key}); 71 | } catch (EmptyResultDataAccessException var5) { 72 | if (LOG.isDebugEnabled()) { 73 | LOG.debug("Failed to find access token for authentication " + authentication); 74 | } 75 | } catch (IllegalArgumentException var6) { 76 | LOG.error("Could not extract access token for authentication " + authentication, var6); 77 | } 78 | 79 | if (accessToken != null && !key.equals(this.authenticationKeyGenerator.extractKey(this.readAuthentication(accessToken.getValue())))) { 80 | this.storeAccessToken(accessToken, authentication); 81 | } 82 | 83 | return accessToken; 84 | } 85 | 86 | /** 87 | * token 更新 88 | * @param authentication 89 | * @return 90 | */ 91 | public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { 92 | String refreshToken = null; 93 | String clientNameParam = authentication.getOAuth2Request().getClientId(); // 请求应用名称 94 | String clientNameRes = null; 95 | 96 | if (token.getRefreshToken() != null) { 97 | refreshToken = token.getRefreshToken().getValue(); 98 | } 99 | 100 | if (this.readAccessToken(token.getValue()) != null) { // 如果token已经存在 101 | this.removeAccessToken(token.getValue()); 102 | } 103 | 104 | // 通过ClientName 查询当前应用ID 105 | try { 106 | clientNameRes = this.jdbcTemplate.queryForObject(this.selectExistClientFromClientNameSql, new RowMapper() { 107 | public String mapRow(ResultSet rs, int rowNum) throws SQLException { 108 | return rs.getString(1); 109 | } 110 | } , new Object[]{clientNameParam}); 111 | } catch (EmptyResultDataAccessException var5) { 112 | if (LOG.isDebugEnabled()) { 113 | LOG.debug("Failed to find access token for ClientName " + clientNameParam); 114 | } 115 | } catch (IllegalArgumentException var6) { 116 | LOG.error("Could not extract access token for ClientName " + clientNameParam, var6); 117 | } 118 | 119 | if(clientNameRes == null) { 120 | throw new ClientRegistrationException("该应用不存在!"); 121 | } 122 | 123 | String tokenValue = token.getValue(); // token 值 124 | 125 | // 更新当前clientId 的token信息 126 | this.jdbcTemplate.update(this.updateAccessTokenSql, 127 | new Object[]{this.extractTokenKey(token.getValue()), tokenValue, new SqlLobValue(this.serializeAccessToken(token)) 128 | , this.authenticationKeyGenerator.extractKey(authentication), new SqlLobValue(this.serializeAuthentication(authentication)) 129 | , this.extractTokenKey(refreshToken), clientNameRes}, new int[]{12, 12, 2004, 12, 2004, 12, 12}); 130 | } 131 | 132 | /** 133 | * 验证token 合法 134 | * @param tokenValue token 135 | * @return 136 | */ 137 | public OAuth2AccessToken readAccessToken(String tokenValue) { 138 | OAuth2AccessToken accessToken = null; 139 | String tokenId = this.extractTokenKey(tokenValue); 140 | try { 141 | // 使用token_id 查询 如果存在说明token已经存在 142 | accessToken = (OAuth2AccessToken)this.jdbcTemplate.queryForObject(this.selectAccessTokenSql, new RowMapper() { 143 | public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException { 144 | return MyJdbcTokenStore.this.deserializeAccessToken(rs.getBytes(2)); 145 | } 146 | }, new Object[]{this.extractTokenKey(tokenValue)}); 147 | } catch (EmptyResultDataAccessException var4) { 148 | if (LOG.isInfoEnabled()) { 149 | LOG.info("Failed to find access token for token " + tokenValue); 150 | } 151 | } catch (IllegalArgumentException var5) { 152 | LOG.warn("Failed to deserialize access token for " + tokenValue, var5); 153 | this.removeAccessToken(tokenValue); 154 | } 155 | 156 | return accessToken; 157 | } 158 | 159 | public void removeAccessToken(OAuth2AccessToken token) { 160 | //this.removeAccessToken(token.getValue()); 161 | } 162 | 163 | public void removeAccessToken(String tokenValue) { 164 | //this.jdbcTemplate.update(this.deleteAccessTokenSql, new Object[]{this.extractTokenKey(tokenValue)}); 165 | } 166 | 167 | public OAuth2Authentication readAuthentication(OAuth2AccessToken token) { 168 | return this.readAuthentication(token.getValue()); 169 | } 170 | 171 | public OAuth2Authentication readAuthentication(String token) { 172 | OAuth2Authentication authentication = null; 173 | String tokenId = this.extractTokenKey(token); 174 | 175 | try { 176 | authentication = (OAuth2Authentication)this.jdbcTemplate.queryForObject(this.selectAccessTokenAuthenticationSql, new RowMapper() { 177 | public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException { 178 | return MyJdbcTokenStore.this.deserializeAuthentication(rs.getBytes(2)); 179 | } 180 | }, new Object[]{this.extractTokenKey(token)}); 181 | } catch (EmptyResultDataAccessException var4) { 182 | if (LOG.isInfoEnabled()) { 183 | LOG.info("Failed to find access token for token " + token); 184 | } 185 | } catch (IllegalArgumentException var5) { 186 | LOG.warn("Failed to deserialize authentication for " + token, var5); 187 | //this.removeAccessToken(token); 188 | } 189 | 190 | return authentication; 191 | } 192 | 193 | public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) { 194 | //this.jdbcTemplate.update(this.insertRefreshTokenSql, new Object[]{this.extractTokenKey(refreshToken.getValue()), new SqlLobValue(this.serializeRefreshToken(refreshToken)), new SqlLobValue(this.serializeAuthentication(authentication))}, new int[]{12, 2004, 2004}); 195 | } 196 | 197 | public OAuth2RefreshToken readRefreshToken(String token) { 198 | OAuth2RefreshToken refreshToken = null; 199 | 200 | /* try { 201 | refreshToken = (OAuth2RefreshToken)this.jdbcTemplate.queryForObject(this.selectRefreshTokenSql, new RowMapper() { 202 | public OAuth2RefreshToken mapRow(ResultSet rs, int rowNum) throws SQLException { 203 | return MyJdbcTokenStore.this.deserializeRefreshToken(rs.getBytes(2)); 204 | } 205 | }, new Object[]{this.extractTokenKey(token)}); 206 | } catch (EmptyResultDataAccessException var4) { 207 | if (LOG.isInfoEnabled()) { 208 | LOG.info("Failed to find refresh token for token " + token); 209 | } 210 | } catch (IllegalArgumentException var5) { 211 | LOG.warn("Failed to deserialize refresh token for token " + token, var5); 212 | this.removeRefreshToken(token); 213 | }*/ 214 | 215 | return refreshToken; 216 | } 217 | 218 | public void removeRefreshToken(OAuth2RefreshToken token) { 219 | //this.removeRefreshToken(token.getValue()); 220 | } 221 | 222 | public void removeRefreshToken(String token) { 223 | //this.jdbcTemplate.update(this.deleteRefreshTokenSql, new Object[]{this.extractTokenKey(token)}); 224 | } 225 | 226 | public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) { 227 | return this.readAuthenticationForRefreshToken(token.getValue()); 228 | } 229 | 230 | public OAuth2Authentication readAuthenticationForRefreshToken(String value) { 231 | OAuth2Authentication authentication = null; 232 | 233 | /*try { 234 | authentication = (OAuth2Authentication)this.jdbcTemplate.queryForObject(this.selectRefreshTokenAuthenticationSql, new RowMapper() { 235 | public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException { 236 | return MyJdbcTokenStore.this.deserializeAuthentication(rs.getBytes(2)); 237 | } 238 | }, new Object[]{this.extractTokenKey(value)}); 239 | } catch (EmptyResultDataAccessException var4) { 240 | if (LOG.isInfoEnabled()) { 241 | LOG.info("Failed to find access token for token " + value); 242 | } 243 | } catch (IllegalArgumentException var5) { 244 | LOG.warn("Failed to deserialize access token for " + value, var5); 245 | this.removeRefreshToken(value); 246 | }*/ 247 | 248 | return authentication; 249 | } 250 | 251 | public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) { 252 | //this.removeAccessTokenUsingRefreshToken(refreshToken.getValue()); 253 | } 254 | 255 | public void removeAccessTokenUsingRefreshToken(String refreshToken) { 256 | //this.jdbcTemplate.update(this.deleteAccessTokenFromRefreshTokenSql, new Object[]{this.extractTokenKey(refreshToken)}, new int[]{12}); 257 | } 258 | 259 | public Collection findTokensByClientId(String clientId) { 260 | Object accessTokens = new ArrayList(); 261 | 262 | try { 263 | accessTokens = this.jdbcTemplate.query(this.selectAccessTokensFromClientIdSql, new SafeAccessTokenRowMapper(), new Object[]{clientId}); 264 | } catch (EmptyResultDataAccessException var4) { 265 | if (LOG.isInfoEnabled()) { 266 | LOG.info("Failed to find access token for clientId " + clientId); 267 | } 268 | } 269 | 270 | List accessTokensRes = this.removeNulls((List)accessTokens); 271 | return accessTokensRes; 272 | } 273 | 274 | public Collection findTokensByUserName(String userName) { 275 | Object accessTokens = new ArrayList(); 276 | 277 | try { 278 | //accessTokens = this.jdbcTemplate.query(this.selectAccessTokensFromUserNameSql, new MyJdbcTokenStore.SafeAccessTokenRowMapper(), new Object[]{userName}); 279 | } catch (EmptyResultDataAccessException var4) { 280 | if (LOG.isInfoEnabled()) { 281 | LOG.info("Failed to find access token for userName " + userName); 282 | } 283 | } 284 | 285 | List accessTokensRes = this.removeNulls((List)accessTokens); 286 | return accessTokensRes; 287 | } 288 | 289 | public Collection findTokensByClientIdAndUserName(String clientId, String userName) { 290 | Object accessTokens = new ArrayList(); 291 | 292 | try { 293 | // accessTokens = this.jdbcTemplate.query(this.selectAccessTokensFromUserNameAndClientIdSql, new MyJdbcTokenStore.SafeAccessTokenRowMapper(), new Object[]{userName, clientId}); 294 | } catch (EmptyResultDataAccessException var5) { 295 | if (LOG.isInfoEnabled()) { 296 | LOG.info("Failed to find access token for clientId " + clientId + " and userName " + userName); 297 | } 298 | } 299 | 300 | List accessTokensRes = this.removeNulls((List)accessTokens); 301 | return accessTokensRes; 302 | } 303 | 304 | private List removeNulls(List accessTokens) { 305 | List tokens = new ArrayList(); 306 | Iterator var3 = accessTokens.iterator(); 307 | 308 | while(var3.hasNext()) { 309 | OAuth2AccessToken token = (OAuth2AccessToken)var3.next(); 310 | if (token != null) { 311 | tokens.add(token); 312 | } 313 | } 314 | 315 | return tokens; 316 | } 317 | 318 | protected String extractTokenKey(String value) { 319 | if (value == null) { 320 | return null; 321 | } else { 322 | MessageDigest digest; 323 | try { 324 | digest = MessageDigest.getInstance("MD5"); 325 | } catch (NoSuchAlgorithmException var5) { 326 | throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK)."); 327 | } 328 | 329 | try { 330 | byte[] bytes = digest.digest(value.getBytes("UTF-8")); 331 | return String.format("%032x", new BigInteger(1, bytes)); 332 | } catch (UnsupportedEncodingException var4) { 333 | throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK)."); 334 | } 335 | } 336 | } 337 | 338 | protected byte[] serializeAccessToken(OAuth2AccessToken token) { 339 | return SerializationUtils.serialize(token); 340 | } 341 | 342 | protected byte[] serializeRefreshToken(OAuth2RefreshToken token) { 343 | return SerializationUtils.serialize(token); 344 | } 345 | 346 | protected byte[] serializeAuthentication(OAuth2Authentication authentication) { 347 | return SerializationUtils.serialize(authentication); 348 | } 349 | 350 | protected OAuth2AccessToken deserializeAccessToken(byte[] token) { 351 | return (OAuth2AccessToken)SerializationUtils.deserialize(token); 352 | } 353 | 354 | protected OAuth2RefreshToken deserializeRefreshToken(byte[] token) { 355 | return (OAuth2RefreshToken)SerializationUtils.deserialize(token); 356 | } 357 | 358 | protected OAuth2Authentication deserializeAuthentication(byte[] authentication) { 359 | return (OAuth2Authentication)SerializationUtils.deserialize(authentication); 360 | } 361 | 362 | public void setSelectAccessTokenSql(String selectAccessTokenSql) { 363 | this.selectAccessTokenSql = selectAccessTokenSql; 364 | } 365 | 366 | public void setSelectExistClientFromClientNameSql(String selectExistClientFromClientNameSql) { 367 | this.selectExistClientFromClientNameSql = selectExistClientFromClientNameSql; 368 | } 369 | 370 | public void setUpdateAccessTokenSql(String updateAccessTokenSql) { 371 | this.updateAccessTokenSql = updateAccessTokenSql; 372 | } 373 | 374 | public void setDeleteAccessTokenSql(String deleteAccessTokenSql) { 375 | this.deleteAccessTokenSql = deleteAccessTokenSql; 376 | } 377 | 378 | public void setSelectAccessTokenAuthenticationSql(String selectAccessTokenAuthenticationSql) { 379 | this.selectAccessTokenAuthenticationSql = selectAccessTokenAuthenticationSql; 380 | } 381 | 382 | public void setSelectAccessTokenFromAuthenticationSql(String selectAccessTokenFromAuthenticationSql) { 383 | this.selectAccessTokenFromAuthenticationSql = selectAccessTokenFromAuthenticationSql; 384 | } 385 | 386 | public void setSelectAccessTokensFromClientIdSql(String selectAccessTokensFromClientIdSql) { 387 | this.selectAccessTokensFromClientIdSql = selectAccessTokensFromClientIdSql; 388 | } 389 | 390 | private final class SafeAccessTokenRowMapper implements RowMapper { 391 | private SafeAccessTokenRowMapper() { 392 | } 393 | 394 | public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException { 395 | try { 396 | return MyJdbcTokenStore.this.deserializeAccessToken(rs.getBytes(2)); 397 | } catch (IllegalArgumentException var5) { 398 | String token = rs.getString(1); 399 | MyJdbcTokenStore.this.jdbcTemplate.update(MyJdbcTokenStore.this.deleteAccessTokenSql, new Object[]{token}); 400 | return null; 401 | } 402 | } 403 | } 404 | } 405 | -------------------------------------------------------------------------------- /oauth2.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat MySQL Data Transfer 3 | 4 | Source Server : localhost_3306 5 | Source Server Version : 50703 6 | Source Host : localhost:3306 7 | Source Database : oauth2 8 | 9 | Target Server Type : MYSQL 10 | Target Server Version : 50703 11 | File Encoding : 65001 12 | 13 | Date: 2018-02-23 11:13:46 14 | */ 15 | 16 | SET FOREIGN_KEY_CHECKS=0; 17 | 18 | -- ---------------------------- 19 | -- Table structure for clientdetails 20 | -- ---------------------------- 21 | DROP TABLE IF EXISTS `clientdetails`; 22 | CREATE TABLE `clientdetails` ( 23 | `appId` varchar(255) NOT NULL, 24 | `resourceIds` varchar(255) DEFAULT NULL, 25 | `appSecret` varchar(255) DEFAULT NULL, 26 | `scope` varchar(255) DEFAULT NULL, 27 | `grantTypes` varchar(255) DEFAULT NULL, 28 | `redirectUrl` varchar(255) DEFAULT NULL, 29 | `authorities` varchar(255) DEFAULT NULL, 30 | `access_token_validity` int(11) DEFAULT NULL, 31 | `refresh_token_validity` int(11) DEFAULT NULL, 32 | `additionalInformation` varchar(255) DEFAULT NULL, 33 | `autoApproveScopes` varchar(255) DEFAULT NULL, 34 | PRIMARY KEY (`appId`) 35 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 36 | 37 | -- ---------------------------- 38 | -- Records of clientdetails 39 | -- ---------------------------- 40 | INSERT INTO `clientdetails` VALUES ('', '', '', '', null, null, null, null, null, null, null); 41 | 42 | -- ---------------------------- 43 | -- Table structure for oauth_access_token 44 | -- ---------------------------- 45 | DROP TABLE IF EXISTS `oauth_access_token`; 46 | CREATE TABLE `oauth_access_token` ( 47 | `token_id` varchar(255) DEFAULT NULL, 48 | `token` blob, 49 | `authentication_id` varchar(255) NOT NULL, 50 | `user_name` varchar(255) DEFAULT NULL, 51 | `client_id` varchar(255) DEFAULT NULL, 52 | `authentication` blob, 53 | `refresh_token` varchar(255) DEFAULT NULL, 54 | PRIMARY KEY (`authentication_id`) 55 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 56 | 57 | -- ---------------------------- 58 | -- Records of oauth_access_token 59 | -- ---------------------------- 60 | INSERT INTO `oauth_access_token` VALUES ('8fabe20ca63f4e74f4bb669c04d385d0', 0xACED0005737200436F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744F4175746832416363657373546F6B656E0CB29E361B24FACE0200064C00156164646974696F6E616C496E666F726D6174696F6E74000F4C6A6176612F7574696C2F4D61703B4C000A65787069726174696F6E7400104C6A6176612F7574696C2F446174653B4C000C72656672657368546F6B656E74003F4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F636F6D6D6F6E2F4F417574683252656672657368546F6B656E3B4C000573636F706574000F4C6A6176612F7574696C2F5365743B4C0009746F6B656E547970657400124C6A6176612F6C616E672F537472696E673B4C000576616C756571007E000578707372001E6A6176612E7574696C2E436F6C6C656374696F6E7324456D7074794D6170593614855ADCE7D002000078707372000E6A6176612E7574696C2E44617465686A81014B59741903000078707708000001616C88640E787372004C6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744578706972696E674F417574683252656672657368546F6B656E2FDF47639DD0C9B70200014C000A65787069726174696F6E71007E0002787200446F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744F417574683252656672657368546F6B656E73E10E0A6354D45E0200014C000576616C756571007E0005787074002464356137656431662D316435302D346337302D613562612D6630373866303338643462327371007E00097708000001620472E9CD78737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65536574801D92D18F9B80550200007872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C0001637400164C6A6176612F7574696C2F436F6C6C656374696F6E3B7870737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000023F40000000000001740003616C6C7874000662656172657274002462313564356137642D393766312D346135322D393532372D303063636230363564376330, '49b96b5d5e639875d4cc21bcbe115a55', null, 'apply', 0xACED0005737200416F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F417574683241757468656E7469636174696F6EBD400B02166252130200024C000D73746F7265645265717565737474003C4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F4F4175746832526571756573743B4C00127573657241757468656E7469636174696F6E7400324C6F72672F737072696E676672616D65776F726B2F73656375726974792F636F72652F41757468656E7469636174696F6E3B787200476F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E416273747261637441757468656E7469636174696F6E546F6B656ED3AA287E6E47640E0200035A000D61757468656E746963617465644C000B617574686F7269746965737400164C6A6176612F7574696C2F436F6C6C656374696F6E3B4C000764657461696C737400124C6A6176612F6C616E672F4F626A6563743B787000737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654C697374FC0F2531B5EC8E100200014C00046C6973747400104C6A6176612F7574696C2F4C6973743B7872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C00016371007E00047870737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A65787000000001770400000001737200426F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E617574686F726974792E53696D706C654772616E746564417574686F7269747900000000000001A40200014C0004726F6C657400124C6A6176612F6C616E672F537472696E673B78707400012A7871007E000C707372003A6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F41757468325265717565737400000000000000010200075A0008617070726F7665644C000B617574686F72697469657371007E00044C000A657874656E73696F6E7374000F4C6A6176612F7574696C2F4D61703B4C000B726564697265637455726971007E000E4C00077265667265736874003B4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F546F6B656E526571756573743B4C000B7265736F7572636549647374000F4C6A6176612F7574696C2F5365743B4C000D726573706F6E7365547970657371007E0014787200386F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E426173655265717565737436287A3EA37169BD0200034C0008636C69656E74496471007E000E4C001172657175657374506172616D657465727371007E00124C000573636F706571007E001478707400056170706C79737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654D6170F1A5A8FE74F507420200014C00016D71007E00127870737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F400000000000067708000000080000000374000A6772616E745F74797065740012636C69656E745F63726564656E7469616C73740009636C69656E745F69647400056170706C7974000573636F7065740003616C6C78737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65536574801D92D18F9B80550200007871007E0009737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000103F4000000000000171007E002178017371007E0025770C000000103F4000000000000171007E000F787371007E001A3F40000000000000770800000010000000007870707371007E0025770C000000103F400000000000017400012A787371007E0025770C000000103F400000000000007870, '5921c04bacdc1124144fe19502308887'); 61 | INSERT INTO `oauth_access_token` VALUES ('8806002ac45779804bfb102a1e670dd3', 0xACED0005737200436F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744F4175746832416363657373546F6B656E0CB29E361B24FACE0200064C00156164646974696F6E616C496E666F726D6174696F6E74000F4C6A6176612F7574696C2F4D61703B4C000A65787069726174696F6E7400104C6A6176612F7574696C2F446174653B4C000C72656672657368546F6B656E74003F4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F636F6D6D6F6E2F4F417574683252656672657368546F6B656E3B4C000573636F706574000F4C6A6176612F7574696C2F5365743B4C0009746F6B656E547970657400124C6A6176612F6C616E672F537472696E673B4C000576616C756571007E000578707372001E6A6176612E7574696C2E436F6C6C656374696F6E7324456D7074794D6170593614855ADCE7D002000078707372000E6A6176612E7574696C2E44617465686A81014B59741903000078707708000001616C7B6D4B787372004C6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744578706972696E674F417574683252656672657368546F6B656E2FDF47639DD0C9B70200014C000A65787069726174696F6E71007E0002787200446F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744F417574683252656672657368546F6B656E73E10E0A6354D45E0200014C000576616C756571007E0005787074002436323561393661652D383461372D343262612D623762392D6663613031376633353862647371007E00097708000001620467074978737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65536574801D92D18F9B80550200007872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C0001637400164C6A6176612F7574696C2F436F6C6C656374696F6E3B7870737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000023F40000000000001740003616C6C7874000662656172657274002463666663663939342D336466342D346361612D386336382D303235373934326635623564, '49b96b5d5e639875d4cc21bcbe115a55\\\\', null, 'apply', 0xACED0005737200416F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F417574683241757468656E7469636174696F6EBD400B02166252130200024C000D73746F7265645265717565737474003C4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F4F4175746832526571756573743B4C00127573657241757468656E7469636174696F6E7400324C6F72672F737072696E676672616D65776F726B2F73656375726974792F636F72652F41757468656E7469636174696F6E3B787200476F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E416273747261637441757468656E7469636174696F6E546F6B656ED3AA287E6E47640E0200035A000D61757468656E746963617465644C000B617574686F7269746965737400164C6A6176612F7574696C2F436F6C6C656374696F6E3B4C000764657461696C737400124C6A6176612F6C616E672F4F626A6563743B787000737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654C697374FC0F2531B5EC8E100200014C00046C6973747400104C6A6176612F7574696C2F4C6973743B7872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C00016371007E00047870737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A65787000000001770400000001737200426F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E617574686F726974792E53696D706C654772616E746564417574686F7269747900000000000001A40200014C0004726F6C657400124C6A6176612F6C616E672F537472696E673B78707400012A7871007E000C707372003A6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F41757468325265717565737400000000000000010200075A0008617070726F7665644C000B617574686F72697469657371007E00044C000A657874656E73696F6E7374000F4C6A6176612F7574696C2F4D61703B4C000B726564697265637455726971007E000E4C00077265667265736874003B4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F546F6B656E526571756573743B4C000B7265736F7572636549647374000F4C6A6176612F7574696C2F5365743B4C000D726573706F6E7365547970657371007E0014787200386F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E426173655265717565737436287A3EA37169BD0200034C0008636C69656E74496471007E000E4C001172657175657374506172616D657465727371007E00124C000573636F706571007E001478707400056170706C79737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654D6170F1A5A8FE74F507420200014C00016D71007E00127870737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F400000000000067708000000080000000374000A6772616E745F74797065740012636C69656E745F63726564656E7469616C73740009636C69656E745F69647400056170706C7974000573636F7065740003616C6C78737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65536574801D92D18F9B80550200007871007E0009737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000103F4000000000000171007E002178017371007E0025770C000000103F4000000000000171007E000F787371007E001A3F40000000000000770800000010000000007870707371007E0025770C000000103F400000000000017400012A787371007E0025770C000000103F400000000000007870, '72f9cfd1ed29151b76e931b0e4b7f0a6'); 62 | INSERT INTO `oauth_access_token` VALUES ('d830b87d4a097a27b104e994ed09c5b0', 0xACED0005737200436F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744F4175746832416363657373546F6B656E0CB29E361B24FACE0200064C00156164646974696F6E616C496E666F726D6174696F6E74000F4C6A6176612F7574696C2F4D61703B4C000A65787069726174696F6E7400104C6A6176612F7574696C2F446174653B4C000C72656672657368546F6B656E74003F4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F636F6D6D6F6E2F4F417574683252656672657368546F6B656E3B4C000573636F706574000F4C6A6176612F7574696C2F5365743B4C0009746F6B656E547970657400124C6A6176612F6C616E672F537472696E673B4C000576616C756571007E000578707372001E6A6176612E7574696C2E436F6C6C656374696F6E7324456D7074794D6170593614855ADCE7D002000078707372000E6A6176612E7574696C2E44617465686A81014B59741903000078707708000001616C90645D787372004C6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744578706972696E674F417574683252656672657368546F6B656E2FDF47639DD0C9B70200014C000A65787069726174696F6E71007E0002787200446F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744F417574683252656672657368546F6B656E73E10E0A6354D45E0200014C000576616C756571007E0005787074002465646462633863312D356630622D343565312D393432352D3338306463386438333065387371007E0009770800000162047BFE5C78737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65536574801D92D18F9B80550200007872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C0001637400164C6A6176612F7574696C2F436F6C6C656374696F6E3B7870737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000023F40000000000001740003616C6C7874000662656172657274002430343931363434372D356439652D346131372D393763662D643933373964326236366465, '550ac96891210bab2ba5988ce831d79a', 'user_1', 'apply', 0xACED0005737200416F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F417574683241757468656E7469636174696F6EBD400B02166252130200024C000D73746F7265645265717565737474003C4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F4F4175746832526571756573743B4C00127573657241757468656E7469636174696F6E7400324C6F72672F737072696E676672616D65776F726B2F73656375726974792F636F72652F41757468656E7469636174696F6E3B787200476F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E416273747261637441757468656E7469636174696F6E546F6B656ED3AA287E6E47640E0200035A000D61757468656E746963617465644C000B617574686F7269746965737400164C6A6176612F7574696C2F436F6C6C656374696F6E3B4C000764657461696C737400124C6A6176612F6C616E672F4F626A6563743B787000737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654C697374FC0F2531B5EC8E100200014C00046C6973747400104C6A6176612F7574696C2F4C6973743B7872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C00016371007E00047870737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A65787000000001770400000001737200426F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E617574686F726974792E53696D706C654772616E746564417574686F7269747900000000000001A40200014C0004726F6C657400124C6A6176612F6C616E672F537472696E673B7870740004555345527871007E000C707372003A6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F41757468325265717565737400000000000000010200075A0008617070726F7665644C000B617574686F72697469657371007E00044C000A657874656E73696F6E7374000F4C6A6176612F7574696C2F4D61703B4C000B726564697265637455726971007E000E4C00077265667265736874003B4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F546F6B656E526571756573743B4C000B7265736F7572636549647374000F4C6A6176612F7574696C2F5365743B4C000D726573706F6E7365547970657371007E0014787200386F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E426173655265717565737436287A3EA37169BD0200034C0008636C69656E74496471007E000E4C001172657175657374506172616D657465727371007E00124C000573636F706571007E001478707400056170706C79737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654D6170F1A5A8FE74F507420200014C00016D71007E00127870737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F400000000000067708000000080000000474000A6772616E745F7479706574000870617373776F7264740009636C69656E745F69647400056170706C7974000573636F7065740003616C6C740008757365726E616D65740006757365725F3178737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65536574801D92D18F9B80550200007871007E0009737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000103F4000000000000171007E002178017371007E0027770C000000103F400000000000017371007E000D7400012A787371007E001A3F40000000000000770800000010000000007870707371007E0027770C000000103F400000000000017400012A787371007E0027770C000000103F40000000000000787372004F6F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E557365726E616D6550617373776F726441757468656E7469636174696F6E546F6B656E00000000000001A40200024C000B63726564656E7469616C7371007E00054C00097072696E636970616C71007E00057871007E0003017371007E00077371007E000B0000000177040000000171007E000F7871007E0033737200176A6176612E7574696C2E4C696E6B6564486173684D617034C04E5C106CC0FB0200015A000B6163636573734F726465727871007E001A3F4000000000000C7708000000100000000571007E001C71007E001D71007E002071007E002174000D636C69656E745F73656372657474000631323334353671007E001E71007E001F71007E002271007E0023780070737200326F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E7573657264657461696C732E5573657200000000000001A40200075A00116163636F756E744E6F6E457870697265645A00106163636F756E744E6F6E4C6F636B65645A001563726564656E7469616C734E6F6E457870697265645A0007656E61626C65644C000B617574686F72697469657371007E00144C000870617373776F726471007E000E4C0008757365726E616D6571007E000E7870010101017371007E0024737200116A6176612E7574696C2E54726565536574DD98509395ED875B0300007870737200466F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E7573657264657461696C732E5573657224417574686F72697479436F6D70617261746F7200000000000001A4020000787077040000000171007E000F7870740006757365725F31, 'fec849fcd652ff02b1c3eeb8dcad7ab9'); 63 | 64 | -- ---------------------------- 65 | -- Table structure for oauth_approvals 66 | -- ---------------------------- 67 | DROP TABLE IF EXISTS `oauth_approvals`; 68 | CREATE TABLE `oauth_approvals` ( 69 | `userId` varchar(255) DEFAULT NULL, 70 | `clientId` varchar(255) DEFAULT NULL, 71 | `scope` varchar(255) DEFAULT NULL, 72 | `status` varchar(10) DEFAULT NULL, 73 | `expiresAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 74 | `lastModifiedAt` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' 75 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 76 | 77 | -- ---------------------------- 78 | -- Records of oauth_approvals 79 | -- ---------------------------- 80 | 81 | -- ---------------------------- 82 | -- Table structure for oauth_client_details 83 | -- ---------------------------- 84 | DROP TABLE IF EXISTS `oauth_client_details`; 85 | CREATE TABLE `oauth_client_details` ( 86 | `client_id` varchar(255) NOT NULL, 87 | `resource_ids` varchar(255) DEFAULT NULL, 88 | `client_secret` varchar(255) DEFAULT NULL, 89 | `scope` varchar(255) DEFAULT NULL, 90 | `authorized_grant_types` varchar(255) DEFAULT NULL, 91 | `web_server_redirect_uri` varchar(255) DEFAULT NULL, 92 | `authorities` varchar(255) DEFAULT NULL, 93 | `access_token_validity` int(11) DEFAULT NULL, 94 | `refresh_token_validity` int(11) DEFAULT NULL, 95 | `additional_information` varchar(255) DEFAULT NULL, 96 | `autoapprove` varchar(255) DEFAULT NULL, 97 | PRIMARY KEY (`client_id`) 98 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 99 | 100 | -- ---------------------------- 101 | -- Records of oauth_client_details 102 | -- ---------------------------- 103 | INSERT INTO `oauth_client_details` VALUES ('apply', '*', '123456', 'all', 'client_credentials,refresh_token,password', '', '*', null, null, null, null); 104 | 105 | -- ---------------------------- 106 | -- Table structure for oauth_client_token 107 | -- ---------------------------- 108 | DROP TABLE IF EXISTS `oauth_client_token`; 109 | CREATE TABLE `oauth_client_token` ( 110 | `token_id` varchar(255) DEFAULT NULL, 111 | `token` blob, 112 | `authentication_id` varchar(255) NOT NULL, 113 | `user_name` varchar(255) DEFAULT NULL, 114 | `client_id` varchar(255) DEFAULT NULL, 115 | PRIMARY KEY (`authentication_id`) 116 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 117 | 118 | -- ---------------------------- 119 | -- Records of oauth_client_token 120 | -- ---------------------------- 121 | 122 | -- ---------------------------- 123 | -- Table structure for oauth_code 124 | -- ---------------------------- 125 | DROP TABLE IF EXISTS `oauth_code`; 126 | CREATE TABLE `oauth_code` ( 127 | `code` varchar(255) DEFAULT NULL, 128 | `authentication` blob 129 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 130 | 131 | -- ---------------------------- 132 | -- Records of oauth_code 133 | -- ---------------------------- 134 | 135 | -- ---------------------------- 136 | -- Table structure for oauth_refresh_token 137 | -- ---------------------------- 138 | DROP TABLE IF EXISTS `oauth_refresh_token`; 139 | CREATE TABLE `oauth_refresh_token` ( 140 | `token_id` varchar(255) DEFAULT NULL, 141 | `token` blob, 142 | `authentication` blob 143 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 144 | 145 | -- ---------------------------- 146 | -- Records of oauth_refresh_token 147 | -- ---------------------------- 148 | INSERT INTO `oauth_refresh_token` VALUES ('72f9cfd1ed29151b76e931b0e4b7f0a6', 0xACED00057372004C6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744578706972696E674F417574683252656672657368546F6B656E2FDF47639DD0C9B70200014C000A65787069726174696F6E7400104C6A6176612F7574696C2F446174653B787200446F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744F417574683252656672657368546F6B656E73E10E0A6354D45E0200014C000576616C75657400124C6A6176612F6C616E672F537472696E673B787074002436323561393661652D383461372D343262612D623762392D6663613031376633353862647372000E6A6176612E7574696C2E44617465686A81014B59741903000078707708000001620467074978, 0xACED0005737200416F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F417574683241757468656E7469636174696F6EBD400B02166252130200024C000D73746F7265645265717565737474003C4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F4F4175746832526571756573743B4C00127573657241757468656E7469636174696F6E7400324C6F72672F737072696E676672616D65776F726B2F73656375726974792F636F72652F41757468656E7469636174696F6E3B787200476F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E416273747261637441757468656E7469636174696F6E546F6B656ED3AA287E6E47640E0200035A000D61757468656E746963617465644C000B617574686F7269746965737400164C6A6176612F7574696C2F436F6C6C656374696F6E3B4C000764657461696C737400124C6A6176612F6C616E672F4F626A6563743B787000737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654C697374FC0F2531B5EC8E100200014C00046C6973747400104C6A6176612F7574696C2F4C6973743B7872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C00016371007E00047870737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A65787000000001770400000001737200426F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E617574686F726974792E53696D706C654772616E746564417574686F7269747900000000000001A40200014C0004726F6C657400124C6A6176612F6C616E672F537472696E673B78707400012A7871007E000C707372003A6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F41757468325265717565737400000000000000010200075A0008617070726F7665644C000B617574686F72697469657371007E00044C000A657874656E73696F6E7374000F4C6A6176612F7574696C2F4D61703B4C000B726564697265637455726971007E000E4C00077265667265736874003B4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F546F6B656E526571756573743B4C000B7265736F7572636549647374000F4C6A6176612F7574696C2F5365743B4C000D726573706F6E7365547970657371007E0014787200386F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E426173655265717565737436287A3EA37169BD0200034C0008636C69656E74496471007E000E4C001172657175657374506172616D657465727371007E00124C000573636F706571007E001478707400056170706C79737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654D6170F1A5A8FE74F507420200014C00016D71007E00127870737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F400000000000067708000000080000000374000A6772616E745F74797065740012636C69656E745F63726564656E7469616C73740009636C69656E745F69647400056170706C7974000573636F7065740003616C6C78737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65536574801D92D18F9B80550200007871007E0009737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000103F4000000000000171007E002178017371007E0025770C000000103F4000000000000171007E000F787371007E001A3F40000000000000770800000010000000007870707371007E0025770C000000103F400000000000017400012A787371007E0025770C000000103F400000000000007870); 149 | INSERT INTO `oauth_refresh_token` VALUES ('5921c04bacdc1124144fe19502308887', 0xACED00057372004C6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744578706972696E674F417574683252656672657368546F6B656E2FDF47639DD0C9B70200014C000A65787069726174696F6E7400104C6A6176612F7574696C2F446174653B787200446F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744F417574683252656672657368546F6B656E73E10E0A6354D45E0200014C000576616C75657400124C6A6176612F6C616E672F537472696E673B787074002464356137656431662D316435302D346337302D613562612D6630373866303338643462327372000E6A6176612E7574696C2E44617465686A81014B59741903000078707708000001620472E9CD78, 0xACED0005737200416F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F417574683241757468656E7469636174696F6EBD400B02166252130200024C000D73746F7265645265717565737474003C4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F4F4175746832526571756573743B4C00127573657241757468656E7469636174696F6E7400324C6F72672F737072696E676672616D65776F726B2F73656375726974792F636F72652F41757468656E7469636174696F6E3B787200476F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E416273747261637441757468656E7469636174696F6E546F6B656ED3AA287E6E47640E0200035A000D61757468656E746963617465644C000B617574686F7269746965737400164C6A6176612F7574696C2F436F6C6C656374696F6E3B4C000764657461696C737400124C6A6176612F6C616E672F4F626A6563743B787000737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654C697374FC0F2531B5EC8E100200014C00046C6973747400104C6A6176612F7574696C2F4C6973743B7872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C00016371007E00047870737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A65787000000001770400000001737200426F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E617574686F726974792E53696D706C654772616E746564417574686F7269747900000000000001A40200014C0004726F6C657400124C6A6176612F6C616E672F537472696E673B78707400012A7871007E000C707372003A6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F41757468325265717565737400000000000000010200075A0008617070726F7665644C000B617574686F72697469657371007E00044C000A657874656E73696F6E7374000F4C6A6176612F7574696C2F4D61703B4C000B726564697265637455726971007E000E4C00077265667265736874003B4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F546F6B656E526571756573743B4C000B7265736F7572636549647374000F4C6A6176612F7574696C2F5365743B4C000D726573706F6E7365547970657371007E0014787200386F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E426173655265717565737436287A3EA37169BD0200034C0008636C69656E74496471007E000E4C001172657175657374506172616D657465727371007E00124C000573636F706571007E001478707400056170706C79737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654D6170F1A5A8FE74F507420200014C00016D71007E00127870737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F400000000000067708000000080000000374000A6772616E745F74797065740012636C69656E745F63726564656E7469616C73740009636C69656E745F69647400056170706C7974000573636F7065740003616C6C78737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65536574801D92D18F9B80550200007871007E0009737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000103F4000000000000171007E002178017371007E0025770C000000103F4000000000000171007E000F787371007E001A3F40000000000000770800000010000000007870707371007E0025770C000000103F400000000000017400012A787371007E0025770C000000103F400000000000007870); 150 | INSERT INTO `oauth_refresh_token` VALUES ('fec849fcd652ff02b1c3eeb8dcad7ab9', 0xACED00057372004C6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744578706972696E674F417574683252656672657368546F6B656E2FDF47639DD0C9B70200014C000A65787069726174696F6E7400104C6A6176612F7574696C2F446174653B787200446F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E636F6D6D6F6E2E44656661756C744F417574683252656672657368546F6B656E73E10E0A6354D45E0200014C000576616C75657400124C6A6176612F6C616E672F537472696E673B787074002465646462633863312D356630622D343565312D393432352D3338306463386438333065387372000E6A6176612E7574696C2E44617465686A81014B5974190300007870770800000162047BFE5C78, 0xACED0005737200416F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F417574683241757468656E7469636174696F6EBD400B02166252130200024C000D73746F7265645265717565737474003C4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F4F4175746832526571756573743B4C00127573657241757468656E7469636174696F6E7400324C6F72672F737072696E676672616D65776F726B2F73656375726974792F636F72652F41757468656E7469636174696F6E3B787200476F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E416273747261637441757468656E7469636174696F6E546F6B656ED3AA287E6E47640E0200035A000D61757468656E746963617465644C000B617574686F7269746965737400164C6A6176612F7574696C2F436F6C6C656374696F6E3B4C000764657461696C737400124C6A6176612F6C616E672F4F626A6563743B787000737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654C697374FC0F2531B5EC8E100200014C00046C6973747400104C6A6176612F7574696C2F4C6973743B7872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C00016371007E00047870737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A65787000000001770400000001737200426F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E617574686F726974792E53696D706C654772616E746564417574686F7269747900000000000001A40200014C0004726F6C657400124C6A6176612F6C616E672F537472696E673B7870740004555345527871007E000C707372003A6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F41757468325265717565737400000000000000010200075A0008617070726F7665644C000B617574686F72697469657371007E00044C000A657874656E73696F6E7374000F4C6A6176612F7574696C2F4D61703B4C000B726564697265637455726971007E000E4C00077265667265736874003B4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F546F6B656E526571756573743B4C000B7265736F7572636549647374000F4C6A6176612F7574696C2F5365743B4C000D726573706F6E7365547970657371007E0014787200386F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E426173655265717565737436287A3EA37169BD0200034C0008636C69656E74496471007E000E4C001172657175657374506172616D657465727371007E00124C000573636F706571007E001478707400056170706C79737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654D6170F1A5A8FE74F507420200014C00016D71007E00127870737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F400000000000067708000000080000000474000A6772616E745F7479706574000870617373776F7264740009636C69656E745F69647400056170706C7974000573636F7065740003616C6C740008757365726E616D65740006757365725F3178737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65536574801D92D18F9B80550200007871007E0009737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000103F4000000000000171007E002178017371007E0027770C000000103F400000000000017371007E000D7400012A787371007E001A3F40000000000000770800000010000000007870707371007E0027770C000000103F400000000000017400012A787371007E0027770C000000103F40000000000000787372004F6F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E557365726E616D6550617373776F726441757468656E7469636174696F6E546F6B656E00000000000001A40200024C000B63726564656E7469616C7371007E00054C00097072696E636970616C71007E00057871007E0003017371007E00077371007E000B0000000177040000000171007E000F7871007E0033737200176A6176612E7574696C2E4C696E6B6564486173684D617034C04E5C106CC0FB0200015A000B6163636573734F726465727871007E001A3F4000000000000C7708000000100000000571007E001C71007E001D71007E002071007E002174000D636C69656E745F73656372657474000631323334353671007E001E71007E001F71007E002271007E0023780070737200326F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E7573657264657461696C732E5573657200000000000001A40200075A00116163636F756E744E6F6E457870697265645A00106163636F756E744E6F6E4C6F636B65645A001563726564656E7469616C734E6F6E457870697265645A0007656E61626C65644C000B617574686F72697469657371007E00144C000870617373776F726471007E000E4C0008757365726E616D6571007E000E7870010101017371007E0024737200116A6176612E7574696C2E54726565536574DD98509395ED875B0300007870737200466F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E7573657264657461696C732E5573657224417574686F72697479436F6D70617261746F7200000000000001A4020000787077040000000171007E000F7870740006757365725F31); 151 | --------------------------------------------------------------------------------