Bladeren bron

新增客户端管理

mrbird 6 jaren geleden
bovenliggende
commit
7efb981d24
22 gewijzigde bestanden met toevoegingen van 493 en 390 verwijderingen
  1. 2 0
      febs-auth/src/main/java/cc/mrbird/febs/auth/FebsAuthApplication.java
  2. 16 44
      febs-auth/src/main/java/cc/mrbird/febs/auth/configure/FebsAuthorizationServerConfigurer.java
  3. 1 1
      febs-auth/src/main/java/cc/mrbird/febs/auth/configure/FebsSecurityConfigure.java
  4. 25 0
      febs-auth/src/main/java/cc/mrbird/febs/auth/configure/FebsWebConfigure.java
  5. 89 0
      febs-auth/src/main/java/cc/mrbird/febs/auth/controller/OAuthClientDetailsController.java
  6. 0 77
      febs-auth/src/main/java/cc/mrbird/febs/auth/controller/OauthCliendetailsController.java
  7. 66 0
      febs-auth/src/main/java/cc/mrbird/febs/auth/entity/OAuthClientDetails.java
  8. 10 0
      febs-auth/src/main/java/cc/mrbird/febs/auth/mapper/OAuthClientDetailsMapper.java
  9. 0 14
      febs-auth/src/main/java/cc/mrbird/febs/auth/mapper/OauthCliendetailsMapper.java
  10. 1 1
      febs-auth/src/main/java/cc/mrbird/febs/auth/properties/FebsAuthProperties.java
  11. 0 55
      febs-auth/src/main/java/cc/mrbird/febs/auth/service/IOauthCliendetailsService.java
  12. 51 0
      febs-auth/src/main/java/cc/mrbird/febs/auth/service/OAuthClientDetailsService.java
  13. 3 72
      febs-auth/src/main/java/cc/mrbird/febs/auth/service/ValidateCodeService.java
  14. 1 1
      febs-auth/src/main/java/cc/mrbird/febs/auth/service/impl/FebsUserDetailService.java
  15. 105 0
      febs-auth/src/main/java/cc/mrbird/febs/auth/service/impl/OAuthClientDetailsServiceImpl.java
  16. 0 73
      febs-auth/src/main/java/cc/mrbird/febs/auth/service/impl/OauthCliendetailsServiceImpl.java
  17. 22 33
      febs-auth/src/main/java/cc/mrbird/febs/auth/service/impl/RedisClientDetailsService.java
  18. 86 0
      febs-auth/src/main/java/cc/mrbird/febs/auth/service/impl/ValidateCodeServiceImpl.java
  19. 11 0
      febs-auth/src/main/java/cc/mrbird/febs/auth/translator/FebsWebResponseExceptionTranslator.java
  20. 3 0
      febs-auth/src/main/resources/ValidationMessages.properties
  21. 1 1
      febs-auth/src/main/resources/febs-auth.properties
  22. 0 18
      febs-auth/src/main/resources/mapper/OauthCliendetailsMapper.xml

+ 2 - 0
febs-auth/src/main/java/cc/mrbird/febs/auth/FebsAuthApplication.java

@@ -7,6 +7,7 @@ import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
 
 @EnableDiscoveryClient
 @EnableFebsLettuceRedis
@@ -14,6 +15,7 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 @EnableFebsServerProtect
 @SpringBootApplication
 @MapperScan("cc.mrbird.febs.auth.mapper")
+@EnableGlobalMethodSecurity(prePostEnabled = true)
 public class FebsAuthApplication {
 
     public static void main(String[] args) {

+ 16 - 44
febs-auth/src/main/java/cc/mrbird/febs/auth/configure/FebsAuthorizationServerConfigurer.java

@@ -1,21 +1,16 @@
 package cc.mrbird.febs.auth.configure;
 
 import cc.mrbird.febs.auth.properties.FebsAuthProperties;
-import cc.mrbird.febs.auth.properties.FebsClientsProperties;
-import cc.mrbird.febs.auth.service.FebsUserDetailService;
-import cc.mrbird.febs.auth.service.RedisClientDetailsService;
+import cc.mrbird.febs.auth.service.impl.FebsUserDetailService;
+import cc.mrbird.febs.auth.service.impl.RedisClientDetailsService;
 import cc.mrbird.febs.auth.translator.FebsWebResponseExceptionTranslator;
-import org.apache.commons.lang3.ArrayUtils;
-import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Primary;
 import org.springframework.data.redis.connection.RedisConnectionFactory;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.crypto.password.PasswordEncoder;
-import org.springframework.security.oauth2.config.annotation.builders.InMemoryClientDetailsServiceBuilder;
 import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
 import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
 import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
@@ -56,25 +51,6 @@ public class FebsAuthorizationServerConfigurer extends AuthorizationServerConfig
 
     @Override
     public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
-//        FebsClientsProperties[] clientsArray = properties.getClients();
-//        InMemoryClientDetailsServiceBuilder builder = clients.inMemory();
-//        if (ArrayUtils.isNotEmpty(clientsArray)) {
-//            for (FebsClientsProperties client : clientsArray) {
-//                if (StringUtils.isBlank(client.getClient())) {
-//                    throw new Exception("client不能为空");
-//                }
-//                if (StringUtils.isBlank(client.getSecret())) {
-//                    throw new Exception("secret不能为空");
-//                }
-//                String[] grantTypes = StringUtils.splitByWholeSeparatorPreserveAllTokens(client.getGrantType(), ",");
-//                builder.withClient(client.getClient())
-//                        .secret(passwordEncoder.encode(client.getSecret()))
-//                        .authorizedGrantTypes(grantTypes)
-//                        .accessTokenValiditySeconds(client.getAccessTokenValiditySeconds())
-//                        .refreshTokenValiditySeconds(client.getRefreshTokenValiditySeconds())
-//                        .scopes(client.getScope());
-//            }
-//        }
         clients.withClientDetails(redisClientDetailsService);
     }
 
@@ -86,25 +62,31 @@ public class FebsAuthorizationServerConfigurer extends AuthorizationServerConfig
                 .userDetailsService(userDetailService)
                 .authenticationManager(authenticationManager)
                 .exceptionTranslator(exceptionTranslator);
-        if(properties.getEnableJwt()){
-            endpoints.accessTokenConverter(jwtAccessTokenConverter());
-        }else {
-            endpoints.tokenServices(defaultTokenServices());
-        }
     }
 
     @Bean
     public TokenStore tokenStore() {
-        if(properties.getEnableJwt()){
+        if (properties.getEnableJwt()) {
             return new JwtTokenStore(jwtAccessTokenConverter());
-        }else {
+        } else {
             RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
-            // 解决每次生成的的token都一样的问题
+            // 解决每次生成的的 token都一样的问题
             redisTokenStore.setAuthenticationKeyGenerator(oAuth2Authentication -> UUID.randomUUID().toString());
             return redisTokenStore;
         }
     }
 
+    @Bean
+    @Primary
+    public DefaultTokenServices defaultTokenServices() {
+        DefaultTokenServices tokenServices = new DefaultTokenServices();
+
+        tokenServices.setTokenStore(tokenStore());
+        tokenServices.setSupportRefreshToken(true);
+        tokenServices.setClientDetailsService(redisClientDetailsService);
+        return tokenServices;
+    }
+
     @Bean
     public JwtAccessTokenConverter jwtAccessTokenConverter() {
         JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
@@ -116,14 +98,4 @@ public class FebsAuthorizationServerConfigurer extends AuthorizationServerConfig
         return accessTokenConverter;
     }
 
-    @Primary
-    @Bean
-    public DefaultTokenServices defaultTokenServices() {
-        DefaultTokenServices tokenServices = new DefaultTokenServices();
-
-        tokenServices.setTokenStore(tokenStore());
-        tokenServices.setSupportRefreshToken(true);
-        tokenServices.setClientDetailsService(redisClientDetailsService);
-        return tokenServices;
-    }
 }

+ 1 - 1
febs-auth/src/main/java/cc/mrbird/febs/auth/configure/FebsSecurityConfigure.java

@@ -1,7 +1,7 @@
 package cc.mrbird.febs.auth.configure;
 
 import cc.mrbird.febs.auth.filter.ValidateCodeFilter;
-import cc.mrbird.febs.auth.service.FebsUserDetailService;
+import cc.mrbird.febs.auth.service.impl.FebsUserDetailService;
 import cc.mrbird.febs.common.entity.constant.EndpointConstant;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;

+ 25 - 0
febs-auth/src/main/java/cc/mrbird/febs/auth/configure/FebsWebConfigure.java

@@ -0,0 +1,25 @@
+package cc.mrbird.febs.auth.configure;
+
+import com.baomidou.mybatisplus.core.parser.ISqlParser;
+import com.baomidou.mybatisplus.extension.parsers.BlockAttackSqlParser;
+import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author MrBird
+ */
+@Configuration
+public class FebsWebConfigure {
+    @Bean
+    public PaginationInterceptor paginationInterceptor() {
+        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
+        List<ISqlParser> sqlParserList = new ArrayList<>();
+        sqlParserList.add(new BlockAttackSqlParser());
+        paginationInterceptor.setSqlParserList(sqlParserList);
+        return paginationInterceptor;
+    }
+}

+ 89 - 0
febs-auth/src/main/java/cc/mrbird/febs/auth/controller/OAuthClientDetailsController.java

@@ -0,0 +1,89 @@
+package cc.mrbird.febs.auth.controller;
+
+import cc.mrbird.febs.auth.entity.OAuthClientDetails;
+import cc.mrbird.febs.auth.service.OAuthClientDetailsService;
+import cc.mrbird.febs.common.entity.FebsResponse;
+import cc.mrbird.febs.common.entity.QueryRequest;
+import cc.mrbird.febs.common.exception.FebsException;
+import cc.mrbird.febs.common.utils.FebsUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotBlank;
+import java.util.Map;
+
+/**
+ * @author Yuuki
+ */
+@Slf4j
+@Validated
+@RestController
+@RequestMapping("client")
+public class OAuthClientDetailsController {
+
+    @Autowired
+    private OAuthClientDetailsService oAuthClientDetailsService;
+
+    @GetMapping("check/{clientId}")
+    public boolean checkUserName(@NotBlank(message = "{required}") @PathVariable String clientId) {
+        OAuthClientDetails client = this.oAuthClientDetailsService.findById(clientId);
+        return client == null;
+    }
+
+    @GetMapping("secret/{clientId}")
+    @PreAuthorize("hasAnyAuthority('client:decrypt')")
+    public FebsResponse getOriginClientSecret(@NotBlank(message = "{required}") @PathVariable String clientId) {
+        OAuthClientDetails client = this.oAuthClientDetailsService.findById(clientId);
+        String origin = client != null ? client.getOriginSecret() : StringUtils.EMPTY;
+        return new FebsResponse().data(origin);
+    }
+
+    @GetMapping
+    @PreAuthorize("hasAnyAuthority('client:view')")
+    public FebsResponse oauthCliendetailsList(QueryRequest request, OAuthClientDetails oAuthClientDetails) {
+        Map<String, Object> dataTable = FebsUtil.getDataTable(this.oAuthClientDetailsService.findOAuthClientDetails(request, oAuthClientDetails));
+        return new FebsResponse().data(dataTable);
+    }
+
+
+    @PostMapping
+    @PreAuthorize("hasAnyAuthority('client:add')")
+    public void addOauthCliendetails(@Valid OAuthClientDetails oAuthClientDetails) throws FebsException {
+        try {
+            this.oAuthClientDetailsService.createOAuthClientDetails(oAuthClientDetails);
+        } catch (Exception e) {
+            String message = "新增客户端失败";
+            log.error(message, e);
+            throw new FebsException(message);
+        }
+    }
+
+    @DeleteMapping
+    @PreAuthorize("hasAnyAuthority('client:delete')")
+    public void deleteOauthCliendetails(@NotBlank(message = "{required}") String clientIds) throws FebsException {
+        try {
+            this.oAuthClientDetailsService.deleteOAuthClientDetails(clientIds);
+        } catch (Exception e) {
+            String message = "删除客户端失败";
+            log.error(message, e);
+            throw new FebsException(message);
+        }
+    }
+
+    @PutMapping
+    @PreAuthorize("hasAnyAuthority('client:update')")
+    public void updateOauthCliendetails(@Valid OAuthClientDetails oAuthClientDetails) throws FebsException {
+        try {
+            this.oAuthClientDetailsService.updateOAuthClientDetails(oAuthClientDetails);
+        } catch (Exception e) {
+            String message = "修改客户端失败";
+            log.error(message, e);
+            throw new FebsException(message);
+        }
+    }
+}

+ 0 - 77
febs-auth/src/main/java/cc/mrbird/febs/auth/controller/OauthCliendetailsController.java

@@ -1,77 +0,0 @@
-package cc.mrbird.febs.auth.controller;
-
-import cc.mrbird.febs.auth.service.IOauthCliendetailsService;
-import cc.mrbird.febs.common.entity.FebsResponse;
-import cc.mrbird.febs.common.entity.QueryRequest;
-import cc.mrbird.febs.common.entity.auth.OauthCliendetails;
-import cc.mrbird.febs.common.exception.FebsException;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import javax.validation.Valid;
-import java.util.Map;
-
-import static cc.mrbird.febs.common.utils.FebsUtil.getDataTable;
-
-/**
- *  Controller
- *
- * @author MrBird
- * @date 2019-09-09 14:13:23
- */
-@Slf4j
-@Validated
-@RestController
-@RequestMapping("client")
-public class OauthCliendetailsController {
-
-    @Autowired
-    private IOauthCliendetailsService oauthCliendetailsService;
-
-
-    @GetMapping
-    @PreAuthorize("hasAnyAuthority('client:view')")
-    public FebsResponse oauthCliendetailsList(QueryRequest request, OauthCliendetails oauthCliendetails) {
-        Map<String, Object> dataTable = getDataTable(this.oauthCliendetailsService.findOauthCliendetailss(request, oauthCliendetails));
-        return new FebsResponse().data(dataTable);
-    }
-
-    @PostMapping
-    @PreAuthorize("hasAnyAuthority('client:add')")
-    public void addOauthCliendetails(@Valid OauthCliendetails oauthCliendetails) throws FebsException {
-        try {
-            this.oauthCliendetailsService.createOauthCliendetails(oauthCliendetails);
-        } catch (Exception e) {
-            String message = "新增OauthCliendetails失败";
-            log.error(message, e);
-            throw new FebsException(message);
-        }
-    }
-
-    @DeleteMapping
-    @PreAuthorize("hasAnyAuthority('client:delete')")
-    public void deleteOauthCliendetails(OauthCliendetails oauthCliendetails) throws FebsException {
-        try {
-            this.oauthCliendetailsService.deleteOauthCliendetails(oauthCliendetails);
-        } catch (Exception e) {
-            String message = "删除OauthCliendetails失败";
-            log.error(message, e);
-            throw new FebsException(message);
-        }
-    }
-
-    @PutMapping
-    @PreAuthorize("hasAnyAuthority('client:update')")
-    public void updateOauthCliendetails(OauthCliendetails oauthCliendetails) throws FebsException {
-        try {
-            this.oauthCliendetailsService.updateOauthCliendetails(oauthCliendetails);
-        } catch (Exception e) {
-            String message = "修改OauthCliendetails失败";
-            log.error(message, e);
-            throw new FebsException(message);
-        }
-    }
-}

+ 66 - 0
febs-auth/src/main/java/cc/mrbird/febs/auth/entity/OAuthClientDetails.java

@@ -0,0 +1,66 @@
+package cc.mrbird.febs.auth.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.io.Serializable;
+
+/**
+ * @author Yuuki
+ */
+@Data
+@TableName("oauth_client_details")
+public class OAuthClientDetails implements Serializable {
+
+    private static final long serialVersionUID = 421783821058285802L;
+
+    @TableId(value = "client_id")
+    @NotBlank(message = "{required}")
+    @Size(max = 255, message = "{noMoreThan}")
+    private String clientId;
+
+    @TableField("resource_ids")
+    @Size(max = 255, message = "{noMoreThan}")
+    private String resourceIds;
+
+    @TableField("client_secret")
+    @NotBlank(message = "{required}")
+    @Size(max = 255, message = "{noMoreThan}")
+    private String clientSecret;
+
+    @TableField("scope")
+    @NotBlank(message = "{required}")
+    @Size(max = 255, message = "{noMoreThan}")
+    private String scope;
+
+    @TableField("authorized_grant_types")
+    @NotBlank(message = "{required}")
+    @Size(max = 255, message = "{noMoreThan}")
+    private String authorizedGrantTypes;
+
+    @TableField("web_server_redirect_uri")
+    @Size(max = 255, message = "{noMoreThan}")
+    private String webServerRedirectUri;
+
+    @TableField("authorities")
+    @Size(max = 255, message = "{noMoreThan}")
+    private String authorities;
+
+    @TableField("access_token_validity")
+    @NotNull(message = "{required}")
+    private Integer accessTokenValidity;
+
+    @TableField("refresh_token_validity")
+    private Integer refreshTokenValidity;
+
+    @TableField("autoapprove")
+    private Byte autoapprove;
+
+    @TableField("origin_secret")
+    private String originSecret;
+}

+ 10 - 0
febs-auth/src/main/java/cc/mrbird/febs/auth/mapper/OAuthClientDetailsMapper.java

@@ -0,0 +1,10 @@
+package cc.mrbird.febs.auth.mapper;
+
+import cc.mrbird.febs.auth.entity.OAuthClientDetails;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * @author Yuuki
+ */
+public interface OAuthClientDetailsMapper extends BaseMapper<OAuthClientDetails> {
+}

+ 0 - 14
febs-auth/src/main/java/cc/mrbird/febs/auth/mapper/OauthCliendetailsMapper.java

@@ -1,14 +0,0 @@
-package cc.mrbird.febs.auth.mapper;
-
-import cc.mrbird.febs.common.entity.auth.OauthCliendetails;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-
-/**
- *  Mapper
- *
- * @author MrBird
- * @date 2019-09-09 14:13:23
- */
-public interface OauthCliendetailsMapper extends BaseMapper<OauthCliendetails> {
-
-}

+ 1 - 1
febs-auth/src/main/java/cc/mrbird/febs/auth/properties/FebsAuthProperties.java

@@ -31,7 +31,7 @@ public class FebsAuthProperties {
      */
     private String jwtAccessKey;
     /**
-     * 是否启用jwt
+     * 是否使用 JWT令牌
      */
     private Boolean enableJwt;
 }

+ 0 - 55
febs-auth/src/main/java/cc/mrbird/febs/auth/service/IOauthCliendetailsService.java

@@ -1,55 +0,0 @@
-package cc.mrbird.febs.auth.service;
-
-
-import cc.mrbird.febs.common.entity.QueryRequest;
-import cc.mrbird.febs.common.entity.auth.OauthCliendetails;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.service.IService;
-
-import java.util.List;
-
-/**
- *  Service接口
- *
- * @author Yuuki
- * @date 2019年9月23日17:14:38
- */
-public interface IOauthCliendetailsService extends IService<OauthCliendetails> {
-    /**
-     * 查询(分页)
-     *
-     * @param request QueryRequest
-     * @param oauthCliendetails oauthCliendetails
-     * @return IPage<OauthCliendetails>
-     */
-    IPage<OauthCliendetails> findOauthCliendetailss(QueryRequest request, OauthCliendetails oauthCliendetails);
-
-    /**
-     * 查询(所有)
-     *
-     * @param oauthCliendetails oauthCliendetails
-     * @return List<OauthCliendetails>
-     */
-    List<OauthCliendetails> findOauthCliendetailss(OauthCliendetails oauthCliendetails);
-
-    /**
-     * 新增
-     *
-     * @param oauthCliendetails oauthCliendetails
-     */
-    void createOauthCliendetails(OauthCliendetails oauthCliendetails);
-
-    /**
-     * 修改
-     *
-     * @param oauthCliendetails oauthCliendetails
-     */
-    void updateOauthCliendetails(OauthCliendetails oauthCliendetails);
-
-    /**
-     * 删除
-     *
-     * @param oauthCliendetails oauthCliendetails
-     */
-    void deleteOauthCliendetails(OauthCliendetails oauthCliendetails);
-}

+ 51 - 0
febs-auth/src/main/java/cc/mrbird/febs/auth/service/OAuthClientDetailsService.java

@@ -0,0 +1,51 @@
+package cc.mrbird.febs.auth.service;
+
+import cc.mrbird.febs.auth.entity.OAuthClientDetails;
+import cc.mrbird.febs.common.entity.QueryRequest;
+import cc.mrbird.febs.common.exception.FebsException;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * @author Yuuki
+ */
+public interface OAuthClientDetailsService extends IService<OAuthClientDetails> {
+
+    /**
+     * 查询(分页)
+     *
+     * @param request            QueryRequest
+     * @param oauthClientDetails oauthClientDetails
+     * @return IPage<OAuthClientDetails>
+     */
+    IPage<OAuthClientDetails> findOAuthClientDetails(QueryRequest request, OAuthClientDetails oauthClientDetails);
+
+    /**
+     * 根据主键查询
+     *
+     * @param clientId clientId
+     * @return OAuthClientDetails
+     */
+    OAuthClientDetails findById(String clientId);
+
+    /**
+     * 新增
+     *
+     * @param oauthClientDetails oauthClientDetails
+     */
+    void createOAuthClientDetails(OAuthClientDetails oauthClientDetails) throws FebsException;
+
+    /**
+     * 修改
+     *
+     * @param oauthClientDetails oauthClientDetails
+     */
+    void updateOAuthClientDetails(OAuthClientDetails oauthClientDetails);
+
+    /**
+     * 删除
+     *
+     * @param clientIds clientIds
+     */
+    void deleteOAuthClientDetails(String clientIds);
+}

+ 3 - 72
febs-auth/src/main/java/cc/mrbird/febs/auth/service/ValidateCodeService.java

@@ -1,37 +1,12 @@
 package cc.mrbird.febs.auth.service;
 
-import cc.mrbird.febs.auth.properties.FebsAuthProperties;
-import cc.mrbird.febs.auth.properties.FebsValidateCodeProperties;
-import cc.mrbird.febs.common.entity.constant.FebsConstant;
-import cc.mrbird.febs.common.entity.constant.ImageTypeConstant;
-import cc.mrbird.febs.common.entity.constant.ParamsConstant;
 import cc.mrbird.febs.common.exception.ValidateCodeException;
-import cc.mrbird.febs.common.service.RedisService;
-import com.wf.captcha.GifCaptcha;
-import com.wf.captcha.SpecCaptcha;
-import com.wf.captcha.base.Captcha;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
-import org.springframework.stereotype.Service;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
-/**
- * 验证码服务
- *
- * @author MrBird
- */
-@Service
-public class ValidateCodeService {
-
-    @Autowired
-    private RedisService redisService;
-    @Autowired
-    private FebsAuthProperties properties;
+public interface ValidateCodeService {
 
     /**
      * 生成验证码
@@ -39,18 +14,7 @@ public class ValidateCodeService {
      * @param request  HttpServletRequest
      * @param response HttpServletResponse
      */
-    public void create(HttpServletRequest request, HttpServletResponse response) throws IOException, ValidateCodeException {
-        String key = request.getParameter(ParamsConstant.VALIDATE_CODE_KEY);
-        if (StringUtils.isBlank(key)) {
-            throw new ValidateCodeException("验证码key不能为空");
-        }
-        FebsValidateCodeProperties code = properties.getCode();
-        setHeader(response, code.getType());
-
-        Captcha captcha = createCaptcha(code);
-        redisService.set(FebsConstant.CODE_PREFIX + key, StringUtils.lowerCase(captcha.text()), code.getTime());
-        captcha.out(response.getOutputStream());
-    }
+    void create(HttpServletRequest request, HttpServletResponse response) throws IOException, ValidateCodeException;
 
     /**
      * 校验验证码
@@ -58,38 +22,5 @@ public class ValidateCodeService {
      * @param key   前端上送 key
      * @param value 前端上送待校验值
      */
-    public void check(String key, String value) throws ValidateCodeException {
-        Object codeInRedis = redisService.get(FebsConstant.CODE_PREFIX + key);
-        if (StringUtils.isBlank(value)) {
-            throw new ValidateCodeException("请输入验证码");
-        }
-        if (codeInRedis == null) {
-            throw new ValidateCodeException("验证码已过期");
-        }
-        if (!StringUtils.equalsIgnoreCase(value, String.valueOf(codeInRedis))) {
-            throw new ValidateCodeException("验证码不正确");
-        }
-    }
-
-    private Captcha createCaptcha(FebsValidateCodeProperties code) {
-        Captcha captcha = null;
-        if (StringUtils.equalsIgnoreCase(code.getType(), ImageTypeConstant.GIF)) {
-            captcha = new GifCaptcha(code.getWidth(), code.getHeight(), code.getLength());
-        } else {
-            captcha = new SpecCaptcha(code.getWidth(), code.getHeight(), code.getLength());
-        }
-        captcha.setCharType(code.getCharType());
-        return captcha;
-    }
-
-    private void setHeader(HttpServletResponse response, String type) {
-        if (StringUtils.equalsIgnoreCase(type, ImageTypeConstant.GIF)) {
-            response.setContentType(MediaType.IMAGE_GIF_VALUE);
-        } else {
-            response.setContentType(MediaType.IMAGE_PNG_VALUE);
-        }
-        response.setHeader(HttpHeaders.PRAGMA, "No-cache");
-        response.setHeader(HttpHeaders.CACHE_CONTROL, "No-cache");
-        response.setDateHeader(HttpHeaders.EXPIRES, 0L);
-    }
+    void check(String key, String value) throws ValidateCodeException;
 }

+ 1 - 1
febs-auth/src/main/java/cc/mrbird/febs/auth/service/FebsUserDetailService.java → febs-auth/src/main/java/cc/mrbird/febs/auth/service/impl/FebsUserDetailService.java

@@ -1,4 +1,4 @@
-package cc.mrbird.febs.auth.service;
+package cc.mrbird.febs.auth.service.impl;
 
 import cc.mrbird.febs.auth.manager.UserManager;
 import cc.mrbird.febs.common.entity.FebsAuthUser;

+ 105 - 0
febs-auth/src/main/java/cc/mrbird/febs/auth/service/impl/OAuthClientDetailsServiceImpl.java

@@ -0,0 +1,105 @@
+package cc.mrbird.febs.auth.service.impl;
+
+import cc.mrbird.febs.auth.entity.OAuthClientDetails;
+import cc.mrbird.febs.auth.mapper.OAuthClientDetailsMapper;
+import cc.mrbird.febs.auth.service.OAuthClientDetailsService;
+import cc.mrbird.febs.common.entity.QueryRequest;
+import cc.mrbird.febs.common.exception.FebsException;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Yuuki
+ */
+@Slf4j
+@Service
+@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
+public class OAuthClientDetailsServiceImpl extends ServiceImpl<OAuthClientDetailsMapper, OAuthClientDetails> implements OAuthClientDetailsService {
+
+    @Autowired
+    private PasswordEncoder passwordEncoder;
+    @Autowired
+    private RedisClientDetailsService redisClientDetailsService;
+
+    @Override
+    public IPage<OAuthClientDetails> findOAuthClientDetails(QueryRequest request, OAuthClientDetails oauthClientDetails) {
+        LambdaQueryWrapper<OAuthClientDetails> queryWrapper = new LambdaQueryWrapper<>();
+        if (StringUtils.isNotBlank(oauthClientDetails.getClientId())) {
+            queryWrapper.eq(OAuthClientDetails::getClientId, oauthClientDetails.getClientId());
+        }
+        Page<OAuthClientDetails> page = new Page<>(request.getPageNum(), request.getPageSize());
+        IPage<OAuthClientDetails> result = this.page(page, queryWrapper);
+
+        List<OAuthClientDetails> records = new ArrayList<>();
+        result.getRecords().forEach(o -> {
+            o.setOriginSecret(null);
+            o.setClientSecret(null);
+            records.add(o);
+        });
+        result.setRecords(records);
+        return result;
+    }
+
+    @Override
+    public OAuthClientDetails findById(String clientId) {
+        return this.baseMapper.selectById(clientId);
+    }
+
+    @Override
+    public void createOAuthClientDetails(OAuthClientDetails oauthClientDetails) throws FebsException {
+        OAuthClientDetails byId = this.findById(oauthClientDetails.getClientId());
+        if (byId != null) {
+            throw new FebsException("该Client已存在");
+        }
+        oauthClientDetails.setOriginSecret(oauthClientDetails.getClientSecret());
+        oauthClientDetails.setClientSecret(passwordEncoder.encode(oauthClientDetails.getClientSecret()));
+        boolean saved = this.save(oauthClientDetails);
+        if (saved) {
+            log.info("缓存Client -> {}", oauthClientDetails);
+            this.redisClientDetailsService.loadClientByClientId(oauthClientDetails.getClientId());
+        }
+    }
+
+    @Override
+    public void updateOAuthClientDetails(OAuthClientDetails oauthClientDetails) {
+        String clientId = oauthClientDetails.getClientId();
+
+        LambdaQueryWrapper<OAuthClientDetails> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(OAuthClientDetails::getClientId, oauthClientDetails.getClientId());
+
+        oauthClientDetails.setClientId(null);
+        oauthClientDetails.setClientSecret(null);
+        boolean updated = this.update(oauthClientDetails, queryWrapper);
+        if (updated) {
+            log.info("更新Client -> {}", oauthClientDetails);
+            this.redisClientDetailsService.removeRedisCache(clientId);
+            this.redisClientDetailsService.loadClientByClientId(clientId);
+        }
+    }
+
+    @Override
+    public void deleteOAuthClientDetails(String clientIds) {
+        Object[] clientIdArray = StringUtils.splitByWholeSeparatorPreserveAllTokens(clientIds, ",");
+        LambdaQueryWrapper<OAuthClientDetails> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.in(OAuthClientDetails::getClientId, clientIdArray);
+        boolean removed = this.remove(queryWrapper);
+        if (removed) {
+            log.info("删除ClientId为({})的Client", clientIds);
+            Arrays.stream(clientIdArray).forEach(c -> this.redisClientDetailsService.removeRedisCache(String.valueOf(c)));
+
+        }
+    }
+}

+ 0 - 73
febs-auth/src/main/java/cc/mrbird/febs/auth/service/impl/OauthCliendetailsServiceImpl.java

@@ -1,73 +0,0 @@
-package cc.mrbird.febs.auth.service.impl;
-
-
-import cc.mrbird.febs.auth.mapper.OauthCliendetailsMapper;
-import cc.mrbird.febs.auth.service.IOauthCliendetailsService;
-import cc.mrbird.febs.auth.service.RedisClientDetailsService;
-import cc.mrbird.febs.common.entity.QueryRequest;
-import cc.mrbird.febs.common.entity.auth.OauthCliendetails;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Propagation;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.List;
-
-/**
- *  Service实现
- *
- * @author Yuuki
- * @date 2019年9月23日17:22:03
- */
-@Service
-@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
-public class OauthCliendetailsServiceImpl extends ServiceImpl<OauthCliendetailsMapper, OauthCliendetails> implements IOauthCliendetailsService {
-
-    @Autowired
-    private OauthCliendetailsMapper oauthCliendetailsMapper;
-    @Autowired
-    private RedisClientDetailsService redisClientDetailsService;
-
-    @Override
-    public IPage<OauthCliendetails> findOauthCliendetailss(QueryRequest request, OauthCliendetails oauthCliendetails) {
-        LambdaQueryWrapper<OauthCliendetails> queryWrapper = new LambdaQueryWrapper<>();
-        // TODO 设置查询条件
-        Page<OauthCliendetails> page = new Page<>(request.getPageNum(), request.getPageSize());
-        return this.page(page, queryWrapper);
-    }
-
-    @Override
-    public List<OauthCliendetails> findOauthCliendetailss(OauthCliendetails oauthCliendetails) {
-	    LambdaQueryWrapper<OauthCliendetails> queryWrapper = new LambdaQueryWrapper<>();
-		// TODO 设置查询条件
-		return this.baseMapper.selectList(queryWrapper);
-    }
-
-    @Override
-    @Transactional
-    public void createOauthCliendetails(OauthCliendetails oauthCliendetails) {
-        this.save(oauthCliendetails);
-    }
-
-    @Override
-    @Transactional
-    public void updateOauthCliendetails(OauthCliendetails oauthCliendetails) {
-        this.saveOrUpdate(oauthCliendetails);
-        // 更新客户端缓存
-        redisClientDetailsService.cacheAndGetClient(oauthCliendetails.getClientId());
-    }
-
-    @Override
-    @Transactional
-    public void deleteOauthCliendetails(OauthCliendetails oauthCliendetails) {
-        LambdaQueryWrapper<OauthCliendetails> wapper = new LambdaQueryWrapper<>();
-	    // TODO 设置删除条件
-	    this.remove(wapper);
-	    // 移除客户端缓存
-	    redisClientDetailsService.removeRedisCache(oauthCliendetails.getClientId());
-	}
-}

+ 22 - 33
febs-auth/src/main/java/cc/mrbird/febs/auth/service/RedisClientDetailsService.java → febs-auth/src/main/java/cc/mrbird/febs/auth/service/impl/RedisClientDetailsService.java

@@ -1,9 +1,10 @@
-package cc.mrbird.febs.auth.service;
+package cc.mrbird.febs.auth.service.impl;
 
 import cc.mrbird.febs.common.service.RedisService;
 import com.alibaba.fastjson.JSONObject;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.logging.log4j.util.Strings;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.oauth2.common.exceptions.InvalidClientException;
 import org.springframework.security.oauth2.provider.ClientDetails;
@@ -15,13 +16,15 @@ import javax.sql.DataSource;
 import java.util.List;
 
 /**
- * 自定义oauth客户端适配
  * @author Yuuki
- * @date 2019年9月23日17:23:04
  */
-@Service
 @Slf4j
+@Service
 public class RedisClientDetailsService extends JdbcClientDetailsService {
+    /**
+     * 缓存 client的 redis key,这里是 hash结构存储
+     */
+    private static final String CACHE_CLIENT_KEY = "client_details";
 
     @Autowired
     RedisService redisService;
@@ -30,19 +33,11 @@ public class RedisClientDetailsService extends JdbcClientDetailsService {
         super(dataSource);
     }
 
-
-    /**
-     * 缓存client的redis key,这里是hash结构存储
-     */
-    private static final String CACHE_CLIENT_KEY = "client_details";
-
     @Override
     public ClientDetails loadClientByClientId(String clientId) throws InvalidClientException {
         ClientDetails clientDetails = null;
-
-        // 先从redis获取
-        String value = (String) redisService.hget(CACHE_CLIENT_KEY,clientId);
-        if (Strings.isBlank(value)) {
+        String value = (String) redisService.hget(CACHE_CLIENT_KEY, clientId);
+        if (StringUtils.isBlank(value)) {
             clientDetails = cacheAndGetClient(clientId);
         } else {
             clientDetails = JSONObject.parseObject(value, BaseClientDetails.class);
@@ -52,32 +47,30 @@ public class RedisClientDetailsService extends JdbcClientDetailsService {
     }
 
     /**
-     * 缓存client并返回client
+     * 缓存 client并返回 client
      *
-     * @param clientId
+     * @param clientId clientId
      */
     public ClientDetails cacheAndGetClient(String clientId) {
-        // 从数据库读取
-        ClientDetails clientDetails = super.loadClientByClientId(clientId);
-        if (clientDetails != null) {// 写入redis缓存
-            redisService.hset(CACHE_CLIENT_KEY,clientId,JSONObject.toJSONString(clientDetails));
-            log.info("缓存clientId:{},{}", clientId, clientDetails);
+        ClientDetails clientDetails = null;
+        clientDetails = super.loadClientByClientId(clientId);
+        if (clientDetails != null) {
+            redisService.hset(CACHE_CLIENT_KEY, clientId, JSONObject.toJSONString(clientDetails));
         }
-
         return clientDetails;
     }
 
     /**
-     * 删除redis缓存
+     * 删除 redis缓存
      *
-     * @param clientId
+     * @param clientId clientId
      */
     public void removeRedisCache(String clientId) {
-        redisService.hdel(CACHE_CLIENT_KEY,clientId);
+        redisService.hdel(CACHE_CLIENT_KEY, clientId);
     }
 
     /**
-     * 将oauth_client_details全表刷入redis
+     * 将 oauth_client_details全表刷入 redis
      */
     public void loadAllClientToCache() {
         if (redisService.hasKey(CACHE_CLIENT_KEY)) {
@@ -86,14 +79,10 @@ public class RedisClientDetailsService extends JdbcClientDetailsService {
         log.info("将oauth_client_details全表刷入redis");
 
         List<ClientDetails> list = super.listClientDetails();
-        if (list.isEmpty()) {
+        if (CollectionUtils.isEmpty(list)) {
             log.error("oauth_client_details表数据为空,请检查");
             return;
         }
-
-        list.forEach(client -> {
-            redisService.hset(CACHE_CLIENT_KEY,client.getClientId(),JSONObject.toJSONString(client));
-        });
+        list.forEach(client -> redisService.hset(CACHE_CLIENT_KEY, client.getClientId(), JSONObject.toJSONString(client)));
     }
-
 }

+ 86 - 0
febs-auth/src/main/java/cc/mrbird/febs/auth/service/impl/ValidateCodeServiceImpl.java

@@ -0,0 +1,86 @@
+package cc.mrbird.febs.auth.service.impl;
+
+import cc.mrbird.febs.auth.properties.FebsAuthProperties;
+import cc.mrbird.febs.auth.properties.FebsValidateCodeProperties;
+import cc.mrbird.febs.auth.service.ValidateCodeService;
+import cc.mrbird.febs.common.entity.constant.FebsConstant;
+import cc.mrbird.febs.common.entity.constant.ImageTypeConstant;
+import cc.mrbird.febs.common.entity.constant.ParamsConstant;
+import cc.mrbird.febs.common.exception.ValidateCodeException;
+import cc.mrbird.febs.common.service.RedisService;
+import com.wf.captcha.GifCaptcha;
+import com.wf.captcha.SpecCaptcha;
+import com.wf.captcha.base.Captcha;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * 验证码服务
+ *
+ * @author MrBird
+ */
+@Service
+public class ValidateCodeServiceImpl implements ValidateCodeService {
+
+    @Autowired
+    private RedisService redisService;
+    @Autowired
+    private FebsAuthProperties properties;
+
+    @Override
+    public void create(HttpServletRequest request, HttpServletResponse response) throws IOException, ValidateCodeException {
+        String key = request.getParameter(ParamsConstant.VALIDATE_CODE_KEY);
+        if (StringUtils.isBlank(key)) {
+            throw new ValidateCodeException("验证码key不能为空");
+        }
+        FebsValidateCodeProperties code = properties.getCode();
+        setHeader(response, code.getType());
+
+        Captcha captcha = createCaptcha(code);
+        redisService.set(FebsConstant.CODE_PREFIX + key, StringUtils.lowerCase(captcha.text()), code.getTime());
+        captcha.out(response.getOutputStream());
+    }
+
+    @Override
+    public void check(String key, String value) throws ValidateCodeException {
+        Object codeInRedis = redisService.get(FebsConstant.CODE_PREFIX + key);
+        if (StringUtils.isBlank(value)) {
+            throw new ValidateCodeException("请输入验证码");
+        }
+        if (codeInRedis == null) {
+            throw new ValidateCodeException("验证码已过期");
+        }
+        if (!StringUtils.equalsIgnoreCase(value, String.valueOf(codeInRedis))) {
+            throw new ValidateCodeException("验证码不正确");
+        }
+    }
+
+    private Captcha createCaptcha(FebsValidateCodeProperties code) {
+        Captcha captcha = null;
+        if (StringUtils.equalsIgnoreCase(code.getType(), ImageTypeConstant.GIF)) {
+            captcha = new GifCaptcha(code.getWidth(), code.getHeight(), code.getLength());
+        } else {
+            captcha = new SpecCaptcha(code.getWidth(), code.getHeight(), code.getLength());
+        }
+        captcha.setCharType(code.getCharType());
+        return captcha;
+    }
+
+    private void setHeader(HttpServletResponse response, String type) {
+        if (StringUtils.equalsIgnoreCase(type, ImageTypeConstant.GIF)) {
+            response.setContentType(MediaType.IMAGE_GIF_VALUE);
+        } else {
+            response.setContentType(MediaType.IMAGE_PNG_VALUE);
+        }
+        response.setHeader(HttpHeaders.PRAGMA, "No-cache");
+        response.setHeader(HttpHeaders.CACHE_CONTROL, "No-cache");
+        response.setDateHeader(HttpHeaders.EXPIRES, 0L);
+    }
+}

+ 11 - 0
febs-auth/src/main/java/cc/mrbird/febs/auth/translator/FebsWebResponseExceptionTranslator.java

@@ -6,6 +6,8 @@ import org.apache.commons.lang3.StringUtils;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
+import org.springframework.security.oauth2.common.exceptions.InvalidScopeException;
+import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
 import org.springframework.security.oauth2.common.exceptions.UnsupportedGrantTypeException;
 import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
 import org.springframework.stereotype.Component;
@@ -29,6 +31,15 @@ public class FebsWebResponseExceptionTranslator implements WebResponseExceptionT
             message = "不支持该认证类型";
             return status.body(response.message(message));
         }
+        if (e instanceof InvalidTokenException
+                && StringUtils.containsIgnoreCase(e.getMessage(), "Invalid refresh token (expired)")) {
+            message = "刷新令牌已过期,请重新登录";
+            return status.body(response.message(message));
+        }
+        if (e instanceof InvalidScopeException) {
+            message = "不是有效的scope值";
+            return status.body(response.message(message));
+        }
         if (e instanceof InvalidGrantException) {
             if (StringUtils.containsIgnoreCase(e.getMessage(), "Invalid refresh token")) {
                 message = "refresh token无效";

+ 3 - 0
febs-auth/src/main/resources/ValidationMessages.properties

@@ -0,0 +1,3 @@
+required=\u4E0D\u80FD\u4E3A\u7A7A
+noMoreThan=\u957f\u5ea6\u4e0d\u80fd\u8d85\u8fc7{max}\u4e2a\u5b57\u7b26
+invalidNumber=\u4e0d\u662f\u6709\u6548\u7684\u6570\u503c

+ 1 - 1
febs-auth/src/main/resources/febs-auth.properties

@@ -12,7 +12,7 @@ febs.auth.clients[1].scope=test
 febs.auth.clients[1].accessTokenValiditySeconds=3600
 
 febs.auth.anonUrl=/actuator/**,/captcha
-febs.auth.enableJwt=false
+febs.auth.enableJwt=true
 febs.auth.jwtAccessKey=febs
 
 febs.auth.code.time=120

+ 0 - 18
febs-auth/src/main/resources/mapper/OauthCliendetailsMapper.xml

@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="cc.mrbird.febs.auth.mapper.OauthCliendetailsMapper">
-
-    <resultMap id="oauthCliendetails" type="cc.mrbird.febs.common.entity.auth.OauthCliendetails">
-        <id column="client_id" jdbcType="varchar" property="clientId"/>
-        <result column="resource_ids" jdbcType="varchar" property="resourceIds"/>
-        <result column="client_secret" jdbcType="varchar" property="clientSecret"/>
-        <result column="scope" jdbcType="varchar" property="scope"/>
-        <result column="authorized_grant_types" jdbcType="varchar" property="authorizedGrantTypes"/>
-        <result column="web_server_redirect_uri" jdbcType="varchar" property="webServerRedirectUri"/>
-        <result column="authorities" jdbcType="varchar" property="authorities"/>
-        <result column="access_token_validity" jdbcType="int" property="accessTokenValidity"/>
-        <result column="refresh_token_validity" jdbcType="int" property="refreshTokenValidity"/>
-        <result column="additional_information" jdbcType="varchar" property="additionalInformation"/>
-        <result column="autoapprove" jdbcType="tinyint" property="autoapprove"/>
-    </resultMap>
-</mapper>