From af576650c19723c4732d80327ed4961e270de3ff Mon Sep 17 00:00:00 2001 From: wanggeng <450292408@qq.com> Date: Wed, 15 Sep 2021 23:41:29 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BA=86OAuth2=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E7=AB=AF=E6=A8=A1=E5=9D=97=EF=BC=8C=E7=AE=80=E5=8C=96?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E4=BA=A4=E4=BA=92=E7=9A=84=E9=95=BF=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- {login-oauth => login-oauth2-server}/pom.xml | 17 +- .../OAuth2AuthorizationServerConfig.java | 156 +++++++++ .../apis/OAuth2ClientController.java | 164 +++++++++ .../route/OAuth2ClientRouteController.java | 37 ++ .../converter/UserAccessTokenConverter.java | 22 ++ .../server/converter/UserAuthConverter.java | 104 ++++++ .../oauth2/server/dao/IOAuth2ClientDao.java | 36 +- ...h2ClientBadClientCredentialsException.java | 31 ++ .../OAuth2ClientExpireException.java | 25 ++ .../OAuth2ClientStateException.java | 24 ++ .../server/pojo/dtos/OAuth2ClientDTO.java | 96 +++--- .../pojo/dtos/OAuth2ClientSimpleDTO.java | 77 +++++ .../server/pojo/pos/OAuth2ClientPO.java | 207 +++++++++++ .../server/pojo/vos/OAuth2ClientVO.java | 208 ++++++++++++ .../server/service/IOAuth2ClientService.java | 172 ++++++++++ .../service/impl/OAuth2ClientServiceImpl.java | 174 ++++++++++ .../impl/OauthClientDetailsServiceImpl.java | 106 ++++++ .../impl/OauthClientTokenServiceImpl.java | 320 ++++++++++++++++++ .../mybatis/mapper/IOAuth2ClientDao.xml | 94 +++-- .../templates/oauth2client}/list.html | 170 +++++----- .../templates/oauth2client}/save.html | 8 +- .../templates/oauth2client}/update.html | 8 +- pom.xml | 24 +- service-oauth-client/pom.xml | 23 -- .../controller/api/OauthClientController.java | 239 ------------- .../client/service/IOauthClientService.java | 130 ------- .../service/impl/OauthClientServiceImpl.java | 149 -------- 27 files changed, 2097 insertions(+), 724 deletions(-) rename {login-oauth => login-oauth2-server}/pom.xml (51%) create mode 100644 login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/config/OAuth2AuthorizationServerConfig.java create mode 100644 login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/controller/apis/OAuth2ClientController.java create mode 100644 login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/controller/route/OAuth2ClientRouteController.java create mode 100644 login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/converter/UserAccessTokenConverter.java create mode 100644 login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/converter/UserAuthConverter.java rename service-oauth-client/src/main/java/ink/wgink/module/oauth/client/dao/IOauthClientDao.java => login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/dao/IOAuth2ClientDao.java (68%) create mode 100644 login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/exceptions/OAuth2ClientBadClientCredentialsException.java create mode 100644 login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/exceptions/OAuth2ClientExpireException.java create mode 100644 login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/exceptions/OAuth2ClientStateException.java rename service-oauth-client/src/main/java/ink/wgink/module/oauth/client/pojo/vos/OauthClientVO.java => login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/pojo/dtos/OAuth2ClientDTO.java (76%) create mode 100644 login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/pojo/dtos/OAuth2ClientSimpleDTO.java create mode 100644 login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/pojo/pos/OAuth2ClientPO.java create mode 100644 login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/pojo/vos/OAuth2ClientVO.java create mode 100644 login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/service/IOAuth2ClientService.java create mode 100644 login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/service/impl/OAuth2ClientServiceImpl.java create mode 100644 login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/service/impl/OauthClientDetailsServiceImpl.java create mode 100644 login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/service/impl/OauthClientTokenServiceImpl.java rename service-oauth-client/src/main/resources/mybatis/mapper/oauthclient-mapper.xml => login-oauth2-server/src/main/resources/mybatis/mapper/IOAuth2ClientDao.xml (70%) rename {service-oauth-client/src/main/resources/templates/oauth/client => login-oauth2-server/src/main/resources/templates/oauth2client}/list.html (72%) rename {service-oauth-client/src/main/resources/templates/oauth/client => login-oauth2-server/src/main/resources/templates/oauth2client}/save.html (98%) rename {service-oauth-client/src/main/resources/templates/oauth/client => login-oauth2-server/src/main/resources/templates/oauth2client}/update.html (98%) delete mode 100644 service-oauth-client/pom.xml delete mode 100644 service-oauth-client/src/main/java/ink/wgink/module/oauth/client/controller/api/OauthClientController.java delete mode 100644 service-oauth-client/src/main/java/ink/wgink/module/oauth/client/service/IOauthClientService.java delete mode 100644 service-oauth-client/src/main/java/ink/wgink/module/oauth/client/service/impl/OauthClientServiceImpl.java diff --git a/login-oauth/pom.xml b/login-oauth2-server/pom.xml similarity index 51% rename from login-oauth/pom.xml rename to login-oauth2-server/pom.xml index 4e09ca4b..b317be53 100644 --- a/login-oauth/pom.xml +++ b/login-oauth2-server/pom.xml @@ -9,7 +9,7 @@ 4.0.0 - login-oauth + login-oauth2-server 单点登录 @@ -18,6 +18,21 @@ login-base 1.0-SNAPSHOT + + ink.wgink + service-menu + 1.0-SNAPSHOT + + + org.springframework.security + spring-security-jwt + 1.0.9.RELEASE + + + org.springframework.security.oauth.boot + spring-security-oauth2-autoconfigure + 2.0.0.RELEASE + \ No newline at end of file diff --git a/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/config/OAuth2AuthorizationServerConfig.java b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/config/OAuth2AuthorizationServerConfig.java new file mode 100644 index 00000000..aca933c9 --- /dev/null +++ b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/config/OAuth2AuthorizationServerConfig.java @@ -0,0 +1,156 @@ +package ink.wgink.login.oauth2.server.config; + +import ink.wgink.login.base.service.user.UserDetailServiceImpl; +import ink.wgink.login.oauth2.server.converter.UserAccessTokenConverter; +import ink.wgink.login.oauth2.server.service.impl.OauthClientDetailsServiceImpl; +import ink.wgink.login.oauth2.server.service.impl.OauthClientTokenServiceImpl; +import ink.wgink.service.user.service.IUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.CompositeTokenGranter; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.TokenGranter; +import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler; +import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; +import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter; +import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; +import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter; +import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; +import org.springframework.security.oauth2.provider.implicit.ImplicitTokenGranter; +import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter; +import org.springframework.security.oauth2.provider.refresh.RefreshTokenGranter; +import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; +import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; + +import java.util.ArrayList; +import java.util.List; + +/** + * @ClassName: OAuth2AuthorizationServerConfig + * @Description: OAuth2认证服务器配置 + * @Author: wanggeng + * @Date: 2021/9/15 4:54 下午 + * @Version: 1.0 + */ +@Configuration +@EnableAuthorizationServer +public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { + + @Autowired + private AuthenticationManager authenticationManager; + @Autowired + private UserDetailServiceImpl userDetailService; + @Autowired + private IUserService userService; + @Autowired + private OauthClientDetailsServiceImpl oAuth2ClientDetailsService; + @Autowired + private OauthClientTokenServiceImpl oAuth2ClientTokenService; + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // 通过内存的方式来完成认证服务 + clients.withClientDetails(oAuth2ClientDetailsService); + } + + @Override + public void configure(AuthorizationServerSecurityConfigurer security) { + // 标识可以全部操作 + security + .tokenKeyAccess("permitAll()") + .checkTokenAccess("permitAll()") + .allowFormAuthenticationForClients(); + } + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) { + // 添加JWT授权机制 + endpoints + .pathMapping("/oauth/authorize", "/oauth_client/authorize") + .pathMapping("/oauth/token", "/oauth_client/token") + .pathMapping("/oauth/token_key", "/oauth_client/token_key") + .pathMapping("/oauth/check_token", "/oauth_client/check_token") + .pathMapping("/oauth/confirm_access", "/oauth_client/confirm_access") + .pathMapping("/oauth/error", "/oauth_client/error") + .authenticationManager(authenticationManager) + .tokenStore(jwtTokenStore()) + .accessTokenConverter(jwtAccessTokenConverter()) + .userDetailsService(userDetailService); + } + + @Bean(name = "jwtTokenStore") + public TokenStore jwtTokenStore() { + return new JwtTokenStore(jwtAccessTokenConverter()); + } + + @Bean(name = "jwtAccessTokenConverter") + public JwtAccessTokenConverter jwtAccessTokenConverter() { + // 添加自定义的认证机制,用来将自定义登陆后客户端拿到的信息 + JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter(); + jwtAccessTokenConverter.setAccessTokenConverter(new UserAccessTokenConverter(userService)); + jwtAccessTokenConverter.setSigningKey("wgink"); + return jwtAccessTokenConverter; + } + + @Bean + public TokenGranter tokenGranter() { + return new TokenGranter() { + private CompositeTokenGranter delegate; + + @Override + public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { + if (delegate == null) { + delegate = new CompositeTokenGranter(getDefaultTokenGranters()); + } + return delegate.grant(grantType, tokenRequest); + } + }; + } + + @Bean + public AuthorizationCodeServices authorizationCodeServices() { + return new InMemoryAuthorizationCodeServices(); + } + + private List getDefaultTokenGranters() { + AuthorizationCodeServices authorizationCodeServices = authorizationCodeServices(); + OAuth2RequestFactory requestFactory = new DefaultOAuth2RequestFactory(oAuth2ClientDetailsService); + List tokenGranters = new ArrayList<>(); + tokenGranters.add(new AuthorizationCodeTokenGranter(oAuth2ClientTokenService, authorizationCodeServices, oAuth2ClientDetailsService, requestFactory)); + tokenGranters.add(new RefreshTokenGranter(oAuth2ClientTokenService, oAuth2ClientDetailsService, requestFactory)); + ImplicitTokenGranter implicit = new ImplicitTokenGranter(oAuth2ClientTokenService, oAuth2ClientDetailsService, requestFactory); + tokenGranters.add(implicit); + tokenGranters.add(new ClientCredentialsTokenGranter(oAuth2ClientTokenService, oAuth2ClientDetailsService, requestFactory)); + if (authenticationManager != null) { + tokenGranters.add(new ResourceOwnerPasswordTokenGranter(authenticationManager, oAuth2ClientTokenService, oAuth2ClientDetailsService, requestFactory)); + } + return tokenGranters; + } + + @Bean + public OAuth2RequestFactory oAuth2RequestFactory() { + OAuth2RequestFactory oAuth2RequestFactory = new DefaultOAuth2RequestFactory(oAuth2ClientDetailsService); + return oAuth2RequestFactory; + } + + @Bean + public UserApprovalHandler userApprovalHandler() { + TokenStoreUserApprovalHandler tokenStoreUserApprovalHandler = new TokenStoreUserApprovalHandler(); + tokenStoreUserApprovalHandler.setClientDetailsService(oAuth2ClientDetailsService); + tokenStoreUserApprovalHandler.setTokenStore(jwtTokenStore()); + tokenStoreUserApprovalHandler.setRequestFactory(oAuth2RequestFactory()); + return tokenStoreUserApprovalHandler; + } + +} diff --git a/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/controller/apis/OAuth2ClientController.java b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/controller/apis/OAuth2ClientController.java new file mode 100644 index 00000000..3dc226cf --- /dev/null +++ b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/controller/apis/OAuth2ClientController.java @@ -0,0 +1,164 @@ +package ink.wgink.login.oauth2.server.controller.apis; + +import ink.wgink.annotation.CheckRequestBodyAnnotation; +import ink.wgink.common.base.DefaultBaseController; +import ink.wgink.exceptions.*; +import ink.wgink.interfaces.consts.ISystemConstant; +import ink.wgink.login.oauth2.server.pojo.dtos.OAuth2ClientDTO; +import ink.wgink.login.oauth2.server.pojo.vos.OAuth2ClientVO; +import ink.wgink.login.oauth2.server.service.IOAuth2ClientService; +import ink.wgink.pojo.ListPage; +import ink.wgink.pojo.result.ErrorResult; +import ink.wgink.pojo.result.SuccessResult; +import ink.wgink.pojo.result.SuccessResultList; +import ink.wgink.util.AesUtil; +import io.swagger.annotations.*; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * @ClassName: OauthClientController + * @Description: Oauth客户端 + * @Author: WangGeng + * @Date: 2019/3/12 11:15 AM + * @Version: 1.0 + **/ +@Api(tags = ISystemConstant.API_TAGS_SYSTEM_PREFIX + "Oauth客户端") +@RestController +@RequestMapping(ISystemConstant.API_PREFIX + "/oauth2client") +public class OAuth2ClientController extends DefaultBaseController { + + @Autowired + private IOAuth2ClientService oAuth2ClientService; + + @ApiOperation(value = "Oauth客户端新增", notes = "Oauth客户端新增接口") + @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) + @PostMapping("save") + @CheckRequestBodyAnnotation + public SuccessResult saveOauthClient(@RequestBody OAuth2ClientVO oAuth2ClientVO) throws Exception { + if (!StringUtils.equals(oAuth2ClientVO.getClientSecret(), + Base64.encodeBase64String( + AesUtil.aesEncoder( + IOAuth2ClientService.OAUTH_CLIENT_RULE, oAuth2ClientVO.getClientId() + ).getBytes("UTF-8") + ))) { + throw new ParamsException("clientId与clientSecret不匹配"); + } + checkParams(oAuth2ClientVO); + oAuth2ClientService.save(oAuth2ClientVO); + return new SuccessResult(); + } + + @ApiOperation(value = "Oauth客户端删除", notes = "Oauth客户端删除接口") + @ApiImplicitParams({ + @ApiImplicitParam(name = "ids", value = "Oauth客户端ID列表,用下划线分隔", paramType = "path", example = "1_2_3") + }) + @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) + @DeleteMapping("remove/{ids}") + public SuccessResult remove(@PathVariable("ids") String ids) throws RemoveException { + oAuth2ClientService.remove(Arrays.asList(ids.split("\\_"))); + return new SuccessResult(); + } + + @ApiOperation(value = "Oauth客户端修改", notes = "Oauth客户端修改接口") + @ApiImplicitParams({ + @ApiImplicitParam(name = "clientId", value = "Oauth客户端ID", paramType = "path") + }) + @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) + @PutMapping("update/{clientId}") + public SuccessResult updateOauthClient(@PathVariable("clientId") String clientId, + @RequestBody OAuth2ClientVO oAuth2ClientVO) throws Exception { + checkParams(oAuth2ClientVO); + oAuth2ClientService.update(clientId, oAuth2ClientVO); + return new SuccessResult(); + } + + /** + * 校验参数 + * + * @param oAuth2ClientVO + * @throws ParamsException + */ + private void checkParams(OAuth2ClientVO oAuth2ClientVO) throws ParamsException { + if (StringUtils.equals(oAuth2ClientVO.getSystemType(), IOAuth2ClientService.OAUTH_CLIENT_SYSTEM_TYPE_THIRD)) { + if (StringUtils.isBlank(oAuth2ClientVO.getSystemState())) { + throw new ParamsException("系统状态不能为空"); + } + if (StringUtils.isBlank(oAuth2ClientVO.getExpireTime())) { + throw new ParamsException("系统到期时间不能为空"); + } + } + } + + @ApiOperation(value = "easyui Oauth客户端列表", notes = "easyui Oauth客户端列表列表接口") + @ApiImplicitParams({ + @ApiImplicitParam(name = "page", value = "当前页码", paramType = "query", dataType = "int", defaultValue = "1"), + @ApiImplicitParam(name = "rows", value = "显示数量", paramType = "query", dataType = "int", defaultValue = "20"), + @ApiImplicitParam(name = "keywords", value = "关键字", paramType = "query", dataType = "String"), + @ApiImplicitParam(name = "startTime", value = "开始时间", paramType = "query", dataType = "String"), + @ApiImplicitParam(name = "endTime", value = "结束时间", paramType = "query", dataType = "String") + }) + @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) + @GetMapping("listpage") + public SuccessResultList> listPage(ListPage page) throws SearchException { + Map params = requestParams(); + page.setParams(params); + return oAuth2ClientService.listPage(page); + } + + @ApiOperation(value = "Oauth客户端列表", notes = "Oauth客户端列表列表接口") + @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) + @GetMapping("list") + public List listOauthClient() throws SearchException { + Map params = requestParams(); + return oAuth2ClientService.list(params); + } + + @ApiOperation(value = "Oauth客户端详情", notes = "Oauth客户端详情接口") + @ApiImplicitParams({ + @ApiImplicitParam(name = "clientId", value = "Oauth客户端ID", paramType = "path") + }) + @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) + @GetMapping("get/{clientId}") + public OAuth2ClientDTO getOauthClient(@PathVariable("clientId") String clientId) throws Exception { + return oAuth2ClientService.get(clientId); + } + + @ApiOperation(value = "Oauth客户端绑定菜单", notes = "Oauth客户端绑定菜单接口,自动创建根节点菜单") + @ApiImplicitParams({ + @ApiImplicitParam(name = "clientId", value = "Oauth客户端ID", paramType = "path"), + @ApiImplicitParam(name = "menuId", value = "菜单ID", paramType = "query") + }) + @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) + @PutMapping("update-menu-init/{clientId}") + public SuccessResult updateMenuInit(@PathVariable("clientId") String clientId, @RequestParam(name = "menuId", required = false) String menuId) { + oAuth2ClientService.updateMenuInit(clientId, menuId); + return new SuccessResult(); + } + + @ApiOperation(value = "清除客户端菜单", notes = "清除客户端菜单菜单") + @ApiImplicitParams({ + @ApiImplicitParam(name = "clientId", value = "Oauth客户端ID", paramType = "path") + }) + @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) + @PutMapping("update-menu-empty/{clientId}") + public SuccessResult updateMenuEmpty(@PathVariable("clientId") String clientId) { + oAuth2ClientService.updateMenuEmpty(clientId); + return new SuccessResult(); + } + + @ApiOperation(value = "Oauth客户端初始化数据", notes = "Oauth客户端初始化数据接口") + @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) + @GetMapping("get-init") + public OAuth2ClientDTO getInitClient() throws Exception { + return oAuth2ClientService.getInit(); + } + + +} diff --git a/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/controller/route/OAuth2ClientRouteController.java b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/controller/route/OAuth2ClientRouteController.java new file mode 100644 index 00000000..57930177 --- /dev/null +++ b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/controller/route/OAuth2ClientRouteController.java @@ -0,0 +1,37 @@ +package ink.wgink.login.oauth2.server.controller.route; + +import ink.wgink.interfaces.consts.ISystemConstant; +import io.swagger.annotations.Api; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.ModelAndView; + +/** + * @ClassName: OAuth2ClientRouteController + * @Description: oAuth2客户端 + * @Author: wanggeng + * @Date: 2021/9/15 9:36 下午 + * @Version: 1.0 + */ +@Api(tags = ISystemConstant.API_TAGS_APP_ROUTE_PREFIX + "Oauth客户端") +@RestController +@RequestMapping(ISystemConstant.ROUTE_PREFIX + "/oauth2client") +public class OAuth2ClientRouteController { + + @GetMapping("list") + public ModelAndView list() { + return new ModelAndView("oauth2client/list"); + } + + @GetMapping("save") + public ModelAndView save() { + return new ModelAndView("oauth2client/save"); + } + + @GetMapping("update") + public ModelAndView update() { + return new ModelAndView("oauth2client/update"); + } + +} diff --git a/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/converter/UserAccessTokenConverter.java b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/converter/UserAccessTokenConverter.java new file mode 100644 index 00000000..2844927e --- /dev/null +++ b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/converter/UserAccessTokenConverter.java @@ -0,0 +1,22 @@ +package ink.wgink.login.oauth2.server.converter; + +import ink.wgink.service.user.service.IUserService; +import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter; + +/** + * @ClassName: UserAccessTokenConverter + * @Description: 用户jwt token + * @Author: WangGeng + * @Date: 2019/2/28 3:26 PM + * @Version: 1.0 + **/ +public class UserAccessTokenConverter extends DefaultAccessTokenConverter { + + public UserAccessTokenConverter(IUserService userService) { + super(); + UserAuthConverter userAuthConverter = new UserAuthConverter(); + userAuthConverter.setUserService(userService); + super.setUserTokenConverter(userAuthConverter); + } + +} diff --git a/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/converter/UserAuthConverter.java b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/converter/UserAuthConverter.java new file mode 100644 index 00000000..e6e5d14f --- /dev/null +++ b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/converter/UserAuthConverter.java @@ -0,0 +1,104 @@ +package ink.wgink.login.oauth2.server.converter; + +import ink.wgink.interfaces.consts.ISystemConstant; +import ink.wgink.interfaces.role.IRoleBaseService; +import ink.wgink.pojo.bos.LoginUser; +import ink.wgink.pojo.bos.UserInfoBO; +import ink.wgink.pojo.dtos.user.UserAttrInfoDTO; +import ink.wgink.service.user.service.IUserService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter; + +import java.util.*; + +/** + * @ClassName: UserAuthConverter + * @Description: 重写用户认证 + * @Author: WangGeng + * @Date: 2019/2/27 4:57 PM + * @Version: 1.0 + **/ +public class UserAuthConverter implements UserAuthenticationConverter { + + private static final Logger LOG = LoggerFactory.getLogger(UserAuthConverter.class); + private IUserService userService; + + public UserAuthConverter() { + } + + @Override + public Map convertUserAuthentication(Authentication authentication) { + Map response = new LinkedHashMap<>(); + response.put("user_name", authentication.getName()); + // 删除token中的权限信息,通过客户端请求获取,减少accessToken长度 + LoginUser loginUser = (LoginUser) authentication.getPrincipal(); + // 传递登录用户 + Map userInfo = new HashMap<>(4); + userInfo.put("userId", loginUser.getUserId()); + userInfo.put("username", loginUser.getUsername()); + userInfo.put("userName", loginUser.getUserName()); + userInfo.put("userPhone", loginUser.getUserPhone()); + userInfo.put("userAvatar", loginUser.getUserAvatar()); + userInfo.put("userEmail", loginUser.getUserEmail()); + userInfo.put("roles", loginUser.getRoles()); + userInfo.put("departments", loginUser.getDepartments()); + userInfo.put("groups", loginUser.getGroups()); + userInfo.put("getPositions", loginUser.getPositions()); + userInfo.put("expandData", loginUser.getExpandData()); + response.put("user_info", userInfo); + return response; + } + + @Override + public Authentication extractAuthentication(Map map) { + // 解析客户端的权限请求 + Object principal = map.get("user_name"); + if (!Objects.isNull(principal)) { + Collection authorities; + String userName = principal.toString(); + // 包含用户信息,则直接抽取其中的用户信息 + Map userInfo = (Map) map.get("user_info"); + + UserInfoBO userInfoBO = new UserInfoBO(); + userInfoBO.setUserId(userInfo.get("userId").toString()); + userInfoBO.setUserUsername(userInfo.get("username").toString()); + userInfoBO.setUserName(userInfo.get("userName").toString()); + userInfoBO.setUserPhone(userInfo.get("userPhone") == null ? "" : userInfo.get("userPhone").toString()); + userInfoBO.setUserAvatar(userInfo.get("userAvatar") == null ? "" : userInfo.get("userAvatar").toString()); + userInfoBO.setUserEmail(userInfo.get("userEmail") == null ? "" : userInfo.get("userEmail").toString()); + userInfoBO. + if (ISystemConstant.ADMIN.equals(userName)) { + } else { + UserAttrInfoDTO userAttrInfoDTO = userService.getUserAttrInfoByUserId(userInfoBO.getUserId()); + userInfoBO.setDepartments(userAttrInfoDTO.getDepartments()); + userInfoBO.setRoles(userAttrInfoDTO.getRoles()); + userInfoBO.setGroups(userAttrInfoDTO.getGroups()); + userInfoBO.setPositions(userAttrInfoDTO.getPositions()); + userInfoBO.setDataAuthority(userAttrInfoDTO.getDataAuthority()); + userInfoBO.setDataAuthorityUserIds(userAttrInfoDTO.getDataAuthorityUserIds()); + userInfoBO.setBaseDepartmentIds(userAttrInfoDTO.getBaseDepartmentIds()); + + + // 设置权限 + authorities = getAuthorities(userAttrInfoDTO.getRoles()); + } + principal = userInfoBO; + LOG.debug("获取用户权限"); + return new UsernamePasswordAuthenticationToken(principal, "N/A", authorities); + } else { + return null; + } + } + + public IUserService getUserService() { + return userService; + } + + public void setUserService(IUserService userService) { + this.userService = userService; + } +} diff --git a/service-oauth-client/src/main/java/ink/wgink/module/oauth/client/dao/IOauthClientDao.java b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/dao/IOAuth2ClientDao.java similarity index 68% rename from service-oauth-client/src/main/java/ink/wgink/module/oauth/client/dao/IOauthClientDao.java rename to login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/dao/IOAuth2ClientDao.java index 656555a1..cb7b811b 100644 --- a/service-oauth-client/src/main/java/ink/wgink/module/oauth/client/dao/IOauthClientDao.java +++ b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/dao/IOAuth2ClientDao.java @@ -1,11 +1,13 @@ -package ink.wgink.module.oauth.client.dao; +package ink.wgink.login.oauth2.server.dao; import ink.wgink.exceptions.RemoveException; import ink.wgink.exceptions.SaveException; import ink.wgink.exceptions.SearchException; import ink.wgink.exceptions.UpdateException; -import ink.wgink.pojo.dtos.oauth.client.OauthClientDTO; -import ink.wgink.pojo.dtos.oauth.client.OauthClientSimpleDTO; +import ink.wgink.interfaces.init.IInitBaseTable; +import ink.wgink.login.oauth2.server.pojo.dtos.OAuth2ClientDTO; +import ink.wgink.login.oauth2.server.pojo.dtos.OAuth2ClientSimpleDTO; +import ink.wgink.login.oauth2.server.pojo.pos.OAuth2ClientPO; import org.springframework.stereotype.Repository; import java.util.List; @@ -19,7 +21,7 @@ import java.util.Map; * @Version: 1.0 **/ @Repository -public interface IOauthClientDao { +public interface IOAuth2ClientDao extends IInitBaseTable { /** * Oauth客户端新增 @@ -52,7 +54,7 @@ public interface IOauthClientDao { * @return * @throws SearchException */ - List list(Map params) throws SearchException; + List list(Map params) throws SearchException; /** * Oauth客户端列表(简单) @@ -61,7 +63,7 @@ public interface IOauthClientDao { * @return * @throws SearchException */ - List listSimple(Map params) throws SearchException; + List listSimple(Map params) throws SearchException; /** * OauthClient详情 @@ -70,7 +72,16 @@ public interface IOauthClientDao { * @return * @throws SearchException */ - OauthClientDTO get(Map params) throws SearchException; + OAuth2ClientDTO get(Map params) throws SearchException; + + /** + * 获取Oauth客户端(单表) + * + * @param params + * @return + * @throws SearchException + */ + OAuth2ClientPO getPO(Map params) throws SearchException; /** * Oauth客户端统计 @@ -82,18 +93,11 @@ public interface IOauthClientDao { Integer count(Map params) throws SearchException; /** - * 清除Oauth客户端菜单 + * 更新菜单 * * @param params * @throws UpdateException */ - void updateMenuEmpty(Map params) throws UpdateException; + void updateMenu(Map params) throws UpdateException; - /** - * 获取Oauth客户端(单表) - * @param params - * @return - * @throws SearchException - */ - OauthClientDTO getSimple(Map params) throws SearchException; } diff --git a/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/exceptions/OAuth2ClientBadClientCredentialsException.java b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/exceptions/OAuth2ClientBadClientCredentialsException.java new file mode 100644 index 00000000..4cf6fb3c --- /dev/null +++ b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/exceptions/OAuth2ClientBadClientCredentialsException.java @@ -0,0 +1,31 @@ +package ink.wgink.login.oauth2.server.exceptions; + +import org.springframework.security.oauth2.common.exceptions.ClientAuthenticationException; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: ClientBadClientCredentialsException + * @Description: 认证失败异常 + * @Author: WangGeng + * @Date: 2020/7/23 11:11 下午 + * @Version: 1.0 + **/ +public class OAuth2ClientBadClientCredentialsException extends ClientAuthenticationException { + + public OAuth2ClientBadClientCredentialsException(String msg) { + super(msg); + } + + @Override + public int getHttpErrorCode() { + return 401; + } + + @Override + public String getOAuth2ErrorCode() { + return "invalid_client"; + } + +} diff --git a/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/exceptions/OAuth2ClientExpireException.java b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/exceptions/OAuth2ClientExpireException.java new file mode 100644 index 00000000..20d8d4c6 --- /dev/null +++ b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/exceptions/OAuth2ClientExpireException.java @@ -0,0 +1,25 @@ +package ink.wgink.login.oauth2.server.exceptions; + +import org.springframework.security.oauth2.provider.ClientRegistrationException; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: ClientExpireException + * @Description: 客户端超时异常 + * @Author: WangGeng + * @Date: 2020/7/22 8:08 下午 + * @Version: 1.0 + **/ +public class OAuth2ClientExpireException extends ClientRegistrationException { + + public OAuth2ClientExpireException(String msg) { + super(msg); + } + + public OAuth2ClientExpireException(String msg, Throwable cause) { + super(msg, cause); + } + +} diff --git a/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/exceptions/OAuth2ClientStateException.java b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/exceptions/OAuth2ClientStateException.java new file mode 100644 index 00000000..04eff58a --- /dev/null +++ b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/exceptions/OAuth2ClientStateException.java @@ -0,0 +1,24 @@ +package ink.wgink.login.oauth2.server.exceptions; + +import org.springframework.security.oauth2.provider.ClientRegistrationException; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: ClientStateException + * @Description: 客户端状态异常 + * @Author: WangGeng + * @Date: 2020/7/22 10:31 下午 + * @Version: 1.0 + **/ +public class OAuth2ClientStateException extends ClientRegistrationException { + + public OAuth2ClientStateException(String msg) { + super(msg); + } + + public OAuth2ClientStateException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/service-oauth-client/src/main/java/ink/wgink/module/oauth/client/pojo/vos/OauthClientVO.java b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/pojo/dtos/OAuth2ClientDTO.java similarity index 76% rename from service-oauth-client/src/main/java/ink/wgink/module/oauth/client/pojo/vos/OauthClientVO.java rename to login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/pojo/dtos/OAuth2ClientDTO.java index 4cd680a3..26d9efcb 100644 --- a/service-oauth-client/src/main/java/ink/wgink/module/oauth/client/pojo/vos/OauthClientVO.java +++ b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/pojo/dtos/OAuth2ClientDTO.java @@ -1,22 +1,18 @@ -package ink.wgink.module.oauth.client.pojo.vos; +package ink.wgink.login.oauth2.server.pojo.dtos; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; /** - * @ClassName: OauthClientVO + * @ClassName: OauthClientDTO * @Description: 授权认证客户端 * @Author: wenc * @Date: 2019/1/8 7:43 PM * @Version: 1.0 **/ @ApiModel -public class OauthClientVO { +public class OAuth2ClientDTO extends OAuth2ClientSimpleDTO { - @ApiModelProperty(name = "clientId", value = "客户端ID") - private String clientId; - @ApiModelProperty(name = "clientName", value = "客户端名称") - private String clientName; @ApiModelProperty(name = "resourceIds", value = "资源ID列表") private String resourceIds; @ApiModelProperty(name = "clientSecret", value = "客户端密码") @@ -25,8 +21,6 @@ public class OauthClientVO { private String scope; @ApiModelProperty(name = "authorizedGrantTypes", value = "授权类型") private String authorizedGrantTypes; - @ApiModelProperty(name = "webServerRedirectUri", value = "重定向链接") - private String webServerRedirectUri; @ApiModelProperty(name = "authorities", value = "权限") private String authorities; @ApiModelProperty(name = "accessTokenValidity", value = "访问令牌时效") @@ -37,6 +31,10 @@ public class OauthClientVO { private String additionalInformation; @ApiModelProperty(name = "autoapprove", value = "自动授权") private String autoapprove; + @ApiModelProperty(name = "menuId", value = "菜单ID") + private String menuId; + @ApiModelProperty(name = "menuName", value = "菜单名称") + private String menuName; @ApiModelProperty(name = "environment", value = "系统环境") private String environment; @ApiModelProperty(name = "systemType", value = "系统类型") @@ -49,25 +47,11 @@ public class OauthClientVO { private String systemSummary; @ApiModelProperty(name = "systemIcon", value = "系统图标") private String systemIcon; - - public String getClientId() { - return clientId == null ? null : clientId.trim(); - } - - public void setClientId(String clientId) { - this.clientId = clientId; - } - - public String getClientName() { - return clientName == null ? null : clientName.trim(); - } - - public void setClientName(String clientName) { - this.clientName = clientName; - } + @ApiModelProperty(name = "gmtCreate", value = "创建时间") + private String gmtCreate; public String getResourceIds() { - return resourceIds == null ? null : resourceIds.trim(); + return resourceIds == null ? "" : resourceIds.trim(); } public void setResourceIds(String resourceIds) { @@ -75,7 +59,7 @@ public class OauthClientVO { } public String getClientSecret() { - return clientSecret == null ? null : clientSecret.trim(); + return clientSecret == null ? "" : clientSecret.trim(); } public void setClientSecret(String clientSecret) { @@ -83,7 +67,7 @@ public class OauthClientVO { } public String getScope() { - return scope == null ? null : scope.trim(); + return scope == null ? "" : scope.trim(); } public void setScope(String scope) { @@ -91,23 +75,15 @@ public class OauthClientVO { } public String getAuthorizedGrantTypes() { - return authorizedGrantTypes == null ? null : authorizedGrantTypes.trim(); + return authorizedGrantTypes == null ? "" : authorizedGrantTypes.trim(); } public void setAuthorizedGrantTypes(String authorizedGrantTypes) { this.authorizedGrantTypes = authorizedGrantTypes; } - public String getWebServerRedirectUri() { - return webServerRedirectUri == null ? null : webServerRedirectUri.trim(); - } - - public void setWebServerRedirectUri(String webServerRedirectUri) { - this.webServerRedirectUri = webServerRedirectUri; - } - public String getAuthorities() { - return authorities == null ? null : authorities.trim(); + return authorities == null ? "" : authorities.trim(); } public void setAuthorities(String authorities) { @@ -131,7 +107,7 @@ public class OauthClientVO { } public String getAdditionalInformation() { - return additionalInformation == null ? null : additionalInformation.trim(); + return additionalInformation == null ? "" : additionalInformation.trim(); } public void setAdditionalInformation(String additionalInformation) { @@ -139,13 +115,29 @@ public class OauthClientVO { } public String getAutoapprove() { - return autoapprove == null ? null : autoapprove.trim(); + return autoapprove == null ? "" : autoapprove.trim(); } public void setAutoapprove(String autoapprove) { this.autoapprove = autoapprove; } + public String getMenuId() { + return menuId == null ? "" : menuId.trim(); + } + + public void setMenuId(String menuId) { + this.menuId = menuId; + } + + public String getMenuName() { + return menuName == null ? "" : menuName.trim(); + } + + public void setMenuName(String menuName) { + this.menuName = menuName; + } + public String getEnvironment() { return environment == null ? "" : environment.trim(); } @@ -194,14 +186,20 @@ public class OauthClientVO { this.systemIcon = systemIcon; } + @Override + public String getGmtCreate() { + return gmtCreate == null ? "" : gmtCreate.trim(); + } + + @Override + public void setGmtCreate(String gmtCreate) { + this.gmtCreate = gmtCreate; + } + @Override public String toString() { final StringBuilder sb = new StringBuilder("{"); - sb.append("\"clientId\":") - .append("\"").append(clientId).append("\""); - sb.append(",\"clientName\":") - .append("\"").append(clientName).append("\""); - sb.append(",\"resourceIds\":") + sb.append("\"resourceIds\":") .append("\"").append(resourceIds).append("\""); sb.append(",\"clientSecret\":") .append("\"").append(clientSecret).append("\""); @@ -209,8 +207,6 @@ public class OauthClientVO { .append("\"").append(scope).append("\""); sb.append(",\"authorizedGrantTypes\":") .append("\"").append(authorizedGrantTypes).append("\""); - sb.append(",\"webServerRedirectUri\":") - .append("\"").append(webServerRedirectUri).append("\""); sb.append(",\"authorities\":") .append("\"").append(authorities).append("\""); sb.append(",\"accessTokenValidity\":") @@ -221,6 +217,10 @@ public class OauthClientVO { .append("\"").append(additionalInformation).append("\""); sb.append(",\"autoapprove\":") .append("\"").append(autoapprove).append("\""); + sb.append(",\"menuId\":") + .append("\"").append(menuId).append("\""); + sb.append(",\"menuName\":") + .append("\"").append(menuName).append("\""); sb.append(",\"environment\":") .append("\"").append(environment).append("\""); sb.append(",\"systemType\":") @@ -233,6 +233,8 @@ public class OauthClientVO { .append("\"").append(systemSummary).append("\""); sb.append(",\"systemIcon\":") .append("\"").append(systemIcon).append("\""); + sb.append(",\"gmtCreate\":") + .append("\"").append(gmtCreate).append("\""); sb.append('}'); return sb.toString(); } diff --git a/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/pojo/dtos/OAuth2ClientSimpleDTO.java b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/pojo/dtos/OAuth2ClientSimpleDTO.java new file mode 100644 index 00000000..5732f8a1 --- /dev/null +++ b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/pojo/dtos/OAuth2ClientSimpleDTO.java @@ -0,0 +1,77 @@ +package ink.wgink.login.oauth2.server.pojo.dtos; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.io.Serializable; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: OauthClientSimpleDTO + * @Description: 客户端简单信息 + * @Author: WangGeng + * @Date: 2020/7/17 18:18 + * @Version: 1.0 + **/ +@ApiModel +public class OAuth2ClientSimpleDTO implements Serializable { + + private static final long serialVersionUID = -1552124710719004198L; + @ApiModelProperty(name = "clientId", value = "客户端ID") + private String clientId; + @ApiModelProperty(name = "clientName", value = "客户端名称") + private String clientName; + @ApiModelProperty(name = "webServerRedirectUri", value = "重定向链接") + private String webServerRedirectUri; + @ApiModelProperty(name = "gmtCreate", value = "创建时间") + private String gmtCreate; + + public String getClientId() { + return clientId == null ? "" : clientId.trim(); + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getClientName() { + return clientName == null ? "" : clientName.trim(); + } + + public void setClientName(String clientName) { + this.clientName = clientName; + } + + public String getWebServerRedirectUri() { + return webServerRedirectUri == null ? "" : webServerRedirectUri.trim(); + } + + public void setWebServerRedirectUri(String webServerRedirectUri) { + this.webServerRedirectUri = webServerRedirectUri; + } + + public String getGmtCreate() { + return gmtCreate == null ? "" : gmtCreate.trim(); + } + + public void setGmtCreate(String gmtCreate) { + this.gmtCreate = gmtCreate; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("{"); + sb.append("\"clientId\":\"") + .append(clientId).append('\"'); + sb.append(",\"clientName\":\"") + .append(clientName).append('\"'); + sb.append(",\"webServerRedirectUri\":\"") + .append(webServerRedirectUri).append('\"'); + sb.append(",\"gmtCreate\":\"") + .append(gmtCreate).append('\"'); + sb.append('}'); + return sb.toString(); + } +} diff --git a/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/pojo/pos/OAuth2ClientPO.java b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/pojo/pos/OAuth2ClientPO.java new file mode 100644 index 00000000..3876bd08 --- /dev/null +++ b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/pojo/pos/OAuth2ClientPO.java @@ -0,0 +1,207 @@ +package ink.wgink.login.oauth2.server.pojo.pos; + +import ink.wgink.login.oauth2.server.pojo.dtos.OAuth2ClientSimpleDTO; +import io.swagger.annotations.ApiModel; + +/** + * @ClassName: OauthClientDTO + * @Description: 授权认证客户端 + * @Author: wenc + * @Date: 2019/1/8 7:43 PM + * @Version: 1.0 + **/ +@ApiModel +public class OAuth2ClientPO extends OAuth2ClientSimpleDTO { + + private String resourceIds; + private String clientSecret; + private String scope; + private String authorizedGrantTypes; + private String authorities; + private Integer accessTokenValidity; + private Integer refreshTokenValidity; + private String additionalInformation; + private String autoapprove; + private String menuId; + private String environment; + private String systemType; + private String systemState; + private String expireTime; + private String systemSummary; + private String systemIcon; + private String gmtCreate; + private String creator; + private String gmtModified; + private String modifier; + private Integer isDelete; + + public String getResourceIds() { + return resourceIds == null ? "" : resourceIds.trim(); + } + + public void setResourceIds(String resourceIds) { + this.resourceIds = resourceIds; + } + + public String getClientSecret() { + return clientSecret == null ? "" : clientSecret.trim(); + } + + public void setClientSecret(String clientSecret) { + this.clientSecret = clientSecret; + } + + public String getScope() { + return scope == null ? "" : scope.trim(); + } + + public void setScope(String scope) { + this.scope = scope; + } + + public String getAuthorizedGrantTypes() { + return authorizedGrantTypes == null ? "" : authorizedGrantTypes.trim(); + } + + public void setAuthorizedGrantTypes(String authorizedGrantTypes) { + this.authorizedGrantTypes = authorizedGrantTypes; + } + + public String getAuthorities() { + return authorities == null ? "" : authorities.trim(); + } + + public void setAuthorities(String authorities) { + this.authorities = authorities; + } + + public Integer getAccessTokenValidity() { + return accessTokenValidity == null ? 0 : accessTokenValidity; + } + + public void setAccessTokenValidity(Integer accessTokenValidity) { + this.accessTokenValidity = accessTokenValidity; + } + + public Integer getRefreshTokenValidity() { + return refreshTokenValidity == null ? 0 : refreshTokenValidity; + } + + public void setRefreshTokenValidity(Integer refreshTokenValidity) { + this.refreshTokenValidity = refreshTokenValidity; + } + + public String getAdditionalInformation() { + return additionalInformation == null ? "" : additionalInformation.trim(); + } + + public void setAdditionalInformation(String additionalInformation) { + this.additionalInformation = additionalInformation; + } + + public String getAutoapprove() { + return autoapprove == null ? "" : autoapprove.trim(); + } + + public void setAutoapprove(String autoapprove) { + this.autoapprove = autoapprove; + } + + public String getMenuId() { + return menuId == null ? "" : menuId.trim(); + } + + public void setMenuId(String menuId) { + this.menuId = menuId; + } + + public String getEnvironment() { + return environment == null ? "" : environment.trim(); + } + + public void setEnvironment(String environment) { + this.environment = environment; + } + + public String getSystemType() { + return systemType == null ? "" : systemType.trim(); + } + + public void setSystemType(String systemType) { + this.systemType = systemType; + } + + public String getSystemState() { + return systemState == null ? "" : systemState.trim(); + } + + public void setSystemState(String systemState) { + this.systemState = systemState; + } + + public String getExpireTime() { + return expireTime == null ? "" : expireTime.trim(); + } + + public void setExpireTime(String expireTime) { + this.expireTime = expireTime; + } + + public String getSystemSummary() { + return systemSummary == null ? "" : systemSummary.trim(); + } + + public void setSystemSummary(String systemSummary) { + this.systemSummary = systemSummary; + } + + public String getSystemIcon() { + return systemIcon == null ? "" : systemIcon.trim(); + } + + public void setSystemIcon(String systemIcon) { + this.systemIcon = systemIcon; + } + + @Override + public String getGmtCreate() { + return gmtCreate == null ? "" : gmtCreate.trim(); + } + + @Override + public void setGmtCreate(String gmtCreate) { + this.gmtCreate = gmtCreate; + } + + public String getCreator() { + return creator == null ? "" : creator.trim(); + } + + public void setCreator(String creator) { + this.creator = creator; + } + + public String getGmtModified() { + return gmtModified == null ? "" : gmtModified.trim(); + } + + public void setGmtModified(String gmtModified) { + this.gmtModified = gmtModified; + } + + public String getModifier() { + return modifier == null ? "" : modifier.trim(); + } + + public void setModifier(String modifier) { + this.modifier = modifier; + } + + public Integer getIsDelete() { + return isDelete == null ? 0 : isDelete; + } + + public void setIsDelete(Integer isDelete) { + this.isDelete = isDelete; + } +} diff --git a/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/pojo/vos/OAuth2ClientVO.java b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/pojo/vos/OAuth2ClientVO.java new file mode 100644 index 00000000..5d1e0968 --- /dev/null +++ b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/pojo/vos/OAuth2ClientVO.java @@ -0,0 +1,208 @@ +package ink.wgink.login.oauth2.server.pojo.vos; + +import ink.wgink.annotation.CheckEmptyAnnotation; +import ink.wgink.annotation.CheckNumberAnnotation; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @ClassName: OauthClientVO + * @Description: 授权认证客户端 + * @Author: wenc + * @Date: 2019/1/8 7:43 PM + * @Version: 1.0 + **/ +@ApiModel +public class OAuth2ClientVO { + + @ApiModelProperty(name = "clientId", value = "客户端ID") + @CheckEmptyAnnotation(name = "客户端ID") + private String clientId; + @ApiModelProperty(name = "clientName", value = "客户端名称") + @CheckEmptyAnnotation(name = "客户端名称") + private String clientName; + @ApiModelProperty(name = "resourceIds", value = "资源ID列表") + private String resourceIds; + @ApiModelProperty(name = "clientSecret", value = "客户端密码") + @CheckEmptyAnnotation(name = "客户端密码") + private String clientSecret; + @ApiModelProperty(name = "scope", value = "范围") + @CheckEmptyAnnotation(name = "范围") + private String scope; + @ApiModelProperty(name = "authorizedGrantTypes", value = "授权类型") + @CheckEmptyAnnotation(name = "授权类型") + private String authorizedGrantTypes; + @ApiModelProperty(name = "webServerRedirectUri", value = "重定向链接") + @CheckEmptyAnnotation(name = "重定向链接") + private String webServerRedirectUri; + @ApiModelProperty(name = "authorities", value = "权限") + @CheckEmptyAnnotation(name = "权限") + private String authorities; + @ApiModelProperty(name = "accessTokenValidity", value = "访问令牌时效") + @CheckNumberAnnotation(name = "访问令牌时效", min = 0) + private Integer accessTokenValidity; + @ApiModelProperty(name = "refreshTokenValidity", value = "刷新令牌时效") + @CheckNumberAnnotation(name = "刷新令牌时效", min = 0) + private Integer refreshTokenValidity; + @ApiModelProperty(name = "additionalInformation", value = "附加信息") + private String additionalInformation; + @ApiModelProperty(name = "autoapprove", value = "自动授权") + private String autoapprove; + @ApiModelProperty(name = "environment", value = "系统环境") + @CheckEmptyAnnotation(name = "系统环境") + private String environment; + @ApiModelProperty(name = "systemType", value = "系统类型") + private String systemType; + @ApiModelProperty(name = "systemState", value = "系统状态") + private String systemState; + @ApiModelProperty(name = "expireTime", value = "系统到期时间") + private String expireTime; + @ApiModelProperty(name = "systemSummary", value = "系统介绍") + private String systemSummary; + @ApiModelProperty(name = "systemIcon", value = "系统图标") + private String systemIcon; + + public String getClientId() { + return clientId == null ? "" : clientId.trim(); + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getClientName() { + return clientName == null ? "" : clientName.trim(); + } + + public void setClientName(String clientName) { + this.clientName = clientName; + } + + public String getResourceIds() { + return resourceIds == null ? "" : resourceIds.trim(); + } + + public void setResourceIds(String resourceIds) { + this.resourceIds = resourceIds; + } + + public String getClientSecret() { + return clientSecret == null ? "" : clientSecret.trim(); + } + + public void setClientSecret(String clientSecret) { + this.clientSecret = clientSecret; + } + + public String getScope() { + return scope == null ? "" : scope.trim(); + } + + public void setScope(String scope) { + this.scope = scope; + } + + public String getAuthorizedGrantTypes() { + return authorizedGrantTypes == null ? "" : authorizedGrantTypes.trim(); + } + + public void setAuthorizedGrantTypes(String authorizedGrantTypes) { + this.authorizedGrantTypes = authorizedGrantTypes; + } + + public String getWebServerRedirectUri() { + return webServerRedirectUri == null ? "" : webServerRedirectUri.trim(); + } + + public void setWebServerRedirectUri(String webServerRedirectUri) { + this.webServerRedirectUri = webServerRedirectUri; + } + + public String getAuthorities() { + return authorities == null ? "" : authorities.trim(); + } + + public void setAuthorities(String authorities) { + this.authorities = authorities; + } + + public Integer getAccessTokenValidity() { + return accessTokenValidity == null ? 0 : accessTokenValidity; + } + + public void setAccessTokenValidity(Integer accessTokenValidity) { + this.accessTokenValidity = accessTokenValidity; + } + + public Integer getRefreshTokenValidity() { + return refreshTokenValidity == null ? 0 : refreshTokenValidity; + } + + public void setRefreshTokenValidity(Integer refreshTokenValidity) { + this.refreshTokenValidity = refreshTokenValidity; + } + + public String getAdditionalInformation() { + return additionalInformation == null ? "" : additionalInformation.trim(); + } + + public void setAdditionalInformation(String additionalInformation) { + this.additionalInformation = additionalInformation; + } + + public String getAutoapprove() { + return autoapprove == null ? "true" : autoapprove.trim(); + } + + public void setAutoapprove(String autoapprove) { + this.autoapprove = autoapprove; + } + + public String getEnvironment() { + return environment == null ? "" : environment.trim(); + } + + public void setEnvironment(String environment) { + this.environment = environment; + } + + public String getSystemType() { + return systemType == null ? "" : systemType.trim(); + } + + public void setSystemType(String systemType) { + this.systemType = systemType; + } + + public String getSystemState() { + return systemState == null ? "" : systemState.trim(); + } + + public void setSystemState(String systemState) { + this.systemState = systemState; + } + + public String getExpireTime() { + return expireTime == null ? "" : expireTime.trim(); + } + + public void setExpireTime(String expireTime) { + this.expireTime = expireTime; + } + + public String getSystemSummary() { + return systemSummary == null ? "" : systemSummary.trim(); + } + + public void setSystemSummary(String systemSummary) { + this.systemSummary = systemSummary; + } + + public String getSystemIcon() { + return systemIcon == null ? "" : systemIcon.trim(); + } + + public void setSystemIcon(String systemIcon) { + this.systemIcon = systemIcon; + } +} diff --git a/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/service/IOAuth2ClientService.java b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/service/IOAuth2ClientService.java new file mode 100644 index 00000000..fdc50612 --- /dev/null +++ b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/service/IOAuth2ClientService.java @@ -0,0 +1,172 @@ +package ink.wgink.login.oauth2.server.service; + +import ink.wgink.login.oauth2.server.pojo.dtos.OAuth2ClientDTO; +import ink.wgink.login.oauth2.server.pojo.dtos.OAuth2ClientSimpleDTO; +import ink.wgink.login.oauth2.server.pojo.pos.OAuth2ClientPO; +import ink.wgink.login.oauth2.server.pojo.vos.OAuth2ClientVO; +import ink.wgink.pojo.ListPage; +import ink.wgink.pojo.result.SuccessResultList; + +import java.util.List; +import java.util.Map; + +/** + * @ClassName: IOauthClientService + * @Description: Oauth客户端 + * @Author: WangGeng + * @Date: 2019/3/12 11:40 AM + * @Version: 1.0 + **/ +public interface IOAuth2ClientService { + + /** + * 客户端加密规则 + */ + String OAUTH_CLIENT_RULE = "WGINK_OAUTH2_CLIENT"; + /** + * 正常环境 + */ + String OAUTH_CLIENT_ENVIRONMENT_FORMAL = "formal"; + /** + * 测试环境 + */ + String OAUTH_CLIENT_ENVIRONMENT_TEST = "test"; + /** + * 内部系统 + */ + String OAUTH_CLIENT_SYSTEM_TYPE_WITHIN = "within"; + /** + * 三方系统 + */ + String OAUTH_CLIENT_SYSTEM_TYPE_THIRD = "third"; + /** + * 状态正常 + */ + String OAUTH_CLIENT_SYSTEM_STATE_NORMAL = "normal"; + /** + * 状态锁定 + */ + String OAUTH_CLIENT_SYSTEM_STATE_LOCKING = "locking"; + + /** + * Oauth客户端新增 + * + * @param params + * @return + * @throws Exception + */ + void save(OAuth2ClientVO oauth2ClientVO) throws Exception; + + /** + * Oauth客户端修改 + * + * @param ids + * @return + */ + void remove(List ids); + + /** + * Oauth客户端修改 + * + * @param clientId + * @param oauth2ClientVO + * @return + * @throws Exception + */ + void update(String clientId, OAuth2ClientVO oauth2ClientVO) throws Exception; + + /** + * Oauth 更新初始化菜单 + * + * @param clientId + * @param menuId + * @return + */ + void updateMenuInit(String clientId, String menuId); + + /** + * 清空Oauth客户端菜单 + * + * @param clientId + * @return + */ + void updateMenuEmpty(String clientId); + + /** + * Oauth客户端列表 + * + * @param params + * @return + */ + List list(Map params); + + + /** + * Oauth客户端列表(简单) + * + * @param params + * @return + */ + List listSimple(Map params); + + /** + * easyUI Oauth客户端列表 + * + * @param page + * @return + */ + SuccessResultList> listPage(ListPage page); + + + /** + * Oauth客户端详情 + * + * @param params + * @return + * @throws Exception + */ + OAuth2ClientDTO get(Map params) throws Exception; + + /** + * 获取Oauth + * + * @param clientId + * @return + * @throws Exception + */ + OAuth2ClientDTO get(String clientId) throws Exception; + + /** + * OAuth2详情 + * + * @param params + * @return + */ + OAuth2ClientPO getPO(Map params); + + /** + * OAuth2详情 + * + * @param clientId + * @return + */ + OAuth2ClientPO getPO(String clientId); + + /** + * Oauth客户端初始化信息 + * + * @return + * @throws Exception + */ + OAuth2ClientDTO getInit() throws Exception; + + /** + * Oauth客户端统计 + * + * @param params + * @return + */ + Integer count(Map params); + + +} diff --git a/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/service/impl/OAuth2ClientServiceImpl.java b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/service/impl/OAuth2ClientServiceImpl.java new file mode 100644 index 00000000..a90d4c6f --- /dev/null +++ b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/service/impl/OAuth2ClientServiceImpl.java @@ -0,0 +1,174 @@ +package ink.wgink.login.oauth2.server.service.impl; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import ink.wgink.common.base.DefaultBaseService; +import ink.wgink.exceptions.RemoveException; +import ink.wgink.exceptions.SaveException; +import ink.wgink.exceptions.SearchException; +import ink.wgink.exceptions.UpdateException; +import ink.wgink.login.oauth2.server.dao.IOAuth2ClientDao; +import ink.wgink.login.oauth2.server.pojo.dtos.OAuth2ClientDTO; +import ink.wgink.login.oauth2.server.pojo.dtos.OAuth2ClientSimpleDTO; +import ink.wgink.login.oauth2.server.pojo.pos.OAuth2ClientPO; +import ink.wgink.login.oauth2.server.pojo.vos.OAuth2ClientVO; +import ink.wgink.login.oauth2.server.service.IOAuth2ClientService; +import ink.wgink.module.menu.pojo.vos.MenuVO; +import ink.wgink.module.menu.service.IMenuService; +import ink.wgink.pojo.ListPage; +import ink.wgink.pojo.result.SuccessResultList; +import ink.wgink.util.AesUtil; +import ink.wgink.util.UUIDUtil; +import ink.wgink.util.map.HashMapUtil; +import org.apache.commons.codec.binary.Base64; +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 java.util.List; +import java.util.Map; + +/** + * @ClassName: OauthClientServiceImpl + * @Description: Oauth客户端 + * @Author: WangGeng + * @Date: 2019/3/12 11:40 AM + * @Version: 1.0 + **/ +@Service +public class OAuth2ClientServiceImpl extends DefaultBaseService implements IOAuth2ClientService { + + @Autowired + private IOAuth2ClientDao oauth2ClientDao; + @Autowired + private IMenuService menuService; + @Autowired + private PasswordEncoder passwordEncoder; + + @Override + public void save(OAuth2ClientVO oauth2ClientVO) throws SaveException { + oauth2ClientVO.setClientSecret(passwordEncoder.encode(oauth2ClientVO.getClientSecret())); + Map params = HashMapUtil.beanToMap(oauth2ClientVO); + setSaveInfo(params); + oauth2ClientDao.save(params); + } + + @Override + public void remove(List ids) throws RemoveException { + Map params = getHashMap(6); + params.put("clientIds", ids); + setUpdateInfo(params); + oauth2ClientDao.remove(params); + } + + @Override + public void update(String clientId, OAuth2ClientVO oauth2ClientVO) throws UpdateException { + Map params = HashMapUtil.beanToMap(oauth2ClientVO); + params.put("clientId", clientId); + setUpdateInfo(params); + oauth2ClientDao.update(params); + } + + + @Override + public void updateMenuInit(String clientId, String menuId) throws UpdateException, SaveException, SearchException { + OAuth2ClientPO oauth2ClientPO = getPO(clientId); + if (!StringUtils.isBlank(oauth2ClientPO.getMenuId())) { + throw new UpdateException("菜单已经绑定", true); + } + Map params = getHashMap(2); + if (StringUtils.isBlank(menuId)) { + LOG.debug("菜单为空,创建菜单:{}", oauth2ClientPO.getClientName()); + MenuVO menuVO = new MenuVO(); + menuVO.setMenuParentId("0"); + menuVO.setMenuName(oauth2ClientPO.getClientName()); + menuVO.setMenuSummary(oauth2ClientPO.getClientName() + "根节点菜单"); + menuVO.setMenuUrl("javascript:void(0);"); + menuVO.setMenuIcon("fa-icon-color-white fa fa-list"); + menuVO.setMenuStatus(0); + menuVO.setMenuType(1); + menuVO.setOpenType(1); + menuVO.setMenuOrder("1"); + String newMenuId = menuService.saveAndReturnId(menuVO); + LOG.debug("绑定菜单:{}", oauth2ClientPO.getClientName()); + params.put("menuId", newMenuId); + } else { + params.put("menuId", menuId); + } + params.put("clientId", clientId); + oauth2ClientDao.updateMenu(params); + } + + @Override + public void updateMenuEmpty(String clientId) throws UpdateException { + Map params = getHashMap(2); + params.put("clientId", clientId); + oauth2ClientDao.updateMenu(params); + } + + @Override + public List list(Map params) throws SearchException { + return oauth2ClientDao.list(params); + } + + @Override + public List listSimple(Map params) throws SearchException { + return oauth2ClientDao.listSimple(params); + } + + @Override + public SuccessResultList> listPage(ListPage page) throws SearchException { + PageHelper.startPage(page.getPage(), page.getRows()); + List oauthClientDTOs = list(page.getParams()); + PageInfo pageInfo = new PageInfo<>(oauthClientDTOs); + return new SuccessResultList<>(oauthClientDTOs, pageInfo.getPageNum(), pageInfo.getTotal()); + } + + @Override + public OAuth2ClientDTO get(Map params) throws Exception { + OAuth2ClientDTO oauthClientDTO = oauth2ClientDao.get(params); + oauthClientDTO.setClientSecret(Base64.encodeBase64String(AesUtil.aesEncoder(OAUTH_CLIENT_RULE, oauthClientDTO.getClientId()).getBytes("UTF-8"))); + return oauthClientDTO; + } + + @Override + public OAuth2ClientDTO get(String clientId) throws Exception { + Map params = getHashMap(2); + params.put("clientId", clientId); + return get(params); + } + + @Override + public OAuth2ClientPO getPO(Map params) { + return oauth2ClientDao.getPO(params); + } + + @Override + public OAuth2ClientPO getPO(String clientId) throws SearchException { + Map params = getHashMap(2); + params.put("clientId", clientId); + return getPO(params); + } + + @Override + public OAuth2ClientDTO getInit() throws Exception { + OAuth2ClientDTO oauthClientDTO = new OAuth2ClientDTO(); + String clientId = UUIDUtil.get32UUID(); + String clientSecret = Base64.encodeBase64String(AesUtil.aesEncoder(OAUTH_CLIENT_RULE, clientId).getBytes("UTF-8")); + oauthClientDTO.setClientId(clientId); + oauthClientDTO.setClientSecret(clientSecret); + oauthClientDTO.setAccessTokenValidity(7200); + oauthClientDTO.setRefreshTokenValidity(7200); + return oauthClientDTO; + } + + + @Override + public Integer count(Map params) throws SearchException { + Integer oauthClientCount = oauth2ClientDao.count(params); + return oauthClientCount == null ? 0 : oauthClientCount; + } + + +} diff --git a/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/service/impl/OauthClientDetailsServiceImpl.java b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/service/impl/OauthClientDetailsServiceImpl.java new file mode 100644 index 00000000..277ddc1e --- /dev/null +++ b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/service/impl/OauthClientDetailsServiceImpl.java @@ -0,0 +1,106 @@ +package ink.wgink.login.oauth2.server.service.impl; + +import com.fasterxml.jackson.databind.ObjectMapper; +import ink.wgink.login.oauth2.server.exceptions.OAuth2ClientExpireException; +import ink.wgink.login.oauth2.server.exceptions.OAuth2ClientStateException; +import ink.wgink.login.oauth2.server.pojo.pos.OAuth2ClientPO; +import ink.wgink.login.oauth2.server.service.IOAuth2ClientService; +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Primary; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.ClientRegistrationException; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: OauthClientDetailsService + * @Description: Oauth客户端业务 + * @Author: WangGeng + * @Date: 2020/7/22 8:03 下午 + * @Version: 1.0 + **/ +@Primary +@Component +public class OauthClientDetailsServiceImpl implements ClientDetailsService { + private static final Logger LOG = LoggerFactory.getLogger(OauthClientDetailsServiceImpl.class); + @Autowired + private IOAuth2ClientService oAuth2ClientService; + + @Override + public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException { + if (StringUtils.isBlank(clientId)) { + throw new OAuth2ClientExpireException("客户端ID不能为空"); + } + OAuth2ClientPO oAuth2ClientPO = oAuth2ClientService.getPO(clientId); + if (oAuth2ClientPO == null) { + throw new OAuth2ClientStateException("客户端不存在"); + } + // 如果是第三方系统,判断到期时间 + if (StringUtils.equals(oAuth2ClientPO.getSystemType(), IOAuth2ClientService.OAUTH_CLIENT_SYSTEM_TYPE_THIRD)) { + String expireTime = oAuth2ClientPO.getExpireTime(); + if (StringUtils.isBlank(oAuth2ClientPO.getSystemState())) { + throw new OAuth2ClientStateException("客户端状态异常"); + } + if (StringUtils.equals(oAuth2ClientPO.getSystemState(), IOAuth2ClientService.OAUTH_CLIENT_SYSTEM_STATE_LOCKING)) { + throw new OAuth2ClientStateException("客户端锁定"); + } + if (StringUtils.isBlank(oAuth2ClientPO.getExpireTime())) { + throw new OAuth2ClientExpireException("客户端到期时间异常"); + } + DateTime now = DateTime.now(); + DateTime expireTimeDateTime = DateTime.parse(expireTime, DateTimeFormat.forPattern("yyyy-MM-dd")); + if (now.isAfter(expireTimeDateTime)) { + throw new OAuth2ClientExpireException("客户端已过期"); + } + } + BaseClientDetails clientDetails = new BaseClientDetails(oAuth2ClientPO.getClientId(), + oAuth2ClientPO.getResourceIds(), + oAuth2ClientPO.getScope(), + oAuth2ClientPO.getAuthorizedGrantTypes(), + oAuth2ClientPO.getAuthorities()); + + clientDetails.setClientSecret(oAuth2ClientPO.getClientSecret()); + clientDetails.setAccessTokenValiditySeconds(oAuth2ClientPO.getAccessTokenValidity()); + clientDetails.setRefreshTokenValiditySeconds(oAuth2ClientPO.getRefreshTokenValidity()); + // 设置附加信息,json格式 + String additionalInformation = oAuth2ClientPO.getAdditionalInformation(); + if (!StringUtils.isBlank(additionalInformation)) { + ObjectMapper objectMapper = new ObjectMapper(); + try { + Map additionalInformationMap = objectMapper.readValue(additionalInformation, Map.class); + clientDetails.setAdditionalInformation(additionalInformationMap); + } catch (IOException e) { + LOG.error(e.getMessage(), e); + } + } + // 设置scope + if (!StringUtils.isBlank(oAuth2ClientPO.getScope())) { + clientDetails.setScope(org.springframework.util.StringUtils.commaDelimitedListToSet(oAuth2ClientPO.getScope())); + } + + if (clientDetails.isAutoApprove(oAuth2ClientPO.getAutoapprove())) { + Set autoApproveScopesSet = new HashSet<>(); + autoApproveScopesSet.add("true"); + clientDetails.setAutoApproveScopes(autoApproveScopesSet); + } else { + clientDetails.setAutoApproveScopes(clientDetails.getScope()); + } + return clientDetails; + } + + +} diff --git a/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/service/impl/OauthClientTokenServiceImpl.java b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/service/impl/OauthClientTokenServiceImpl.java new file mode 100644 index 00000000..86e6ad4b --- /dev/null +++ b/login-oauth2-server/src/main/java/ink/wgink/login/oauth2/server/service/impl/OauthClientTokenServiceImpl.java @@ -0,0 +1,320 @@ +package ink.wgink.login.oauth2.server.service.impl; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.oauth2.common.*; +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.provider.*; +import org.springframework.security.oauth2.provider.token.*; +import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.Assert; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.Set; +import java.util.UUID; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: OauthClientTokenService + * @Description: Oauth客户端Token + * @Author: WangGeng + * @Date: 2020/7/26 9:33 上午 + * @Version: 1.0 + **/ +@Component +public class OauthClientTokenServiceImpl implements AuthorizationServerTokenServices, ResourceServerTokenServices, ConsumerTokenServices, InitializingBean { + + private int refreshTokenValiditySeconds = 7200; + private int accessTokenValiditySeconds = 7200; + private boolean supportRefreshToken = true; + private boolean reuseRefreshToken = true; + @Resource(name = "jwtTokenStore") + private TokenStore tokenStore; + @Autowired + private ClientDetailsService clientDetailsService; + @Resource(name = "jwtAccessTokenConverter") + private TokenEnhancer accessTokenEnhancer; + @Autowired + private AuthenticationManager authenticationManager; + + public OauthClientTokenServiceImpl() { + } + + @Override + public void afterPropertiesSet() throws Exception { + Assert.notNull(this.tokenStore, "tokenStore must be set"); + } + + @Override + @Transactional + public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException { + OAuth2AccessToken existingAccessToken = this.tokenStore.getAccessToken(authentication); + OAuth2RefreshToken refreshToken = null; + if (existingAccessToken != null) { + if (!existingAccessToken.isExpired()) { + this.tokenStore.storeAccessToken(existingAccessToken, authentication); + return existingAccessToken; + } + if (existingAccessToken.getRefreshToken() != null) { + refreshToken = existingAccessToken.getRefreshToken(); + this.tokenStore.removeRefreshToken(refreshToken); + } + this.tokenStore.removeAccessToken(existingAccessToken); + } + + if (refreshToken == null) { + refreshToken = this.createRefreshToken(authentication); + } else if (refreshToken instanceof ExpiringOAuth2RefreshToken) { + ExpiringOAuth2RefreshToken expiring = (ExpiringOAuth2RefreshToken) refreshToken; + if (System.currentTimeMillis() > expiring.getExpiration().getTime()) { + refreshToken = this.createRefreshToken(authentication); + } + } + + OAuth2AccessToken accessToken = this.createAccessToken(authentication, refreshToken); + this.tokenStore.storeAccessToken(accessToken, authentication); + refreshToken = accessToken.getRefreshToken(); + if (refreshToken != null) { + this.tokenStore.storeRefreshToken(refreshToken, authentication); + } + + return accessToken; + } + + @Override + @Transactional(noRollbackFor = {InvalidTokenException.class, InvalidGrantException.class}) + public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenRequest tokenRequest) throws AuthenticationException { + if (!this.supportRefreshToken) { + throw new InvalidGrantException("无效的刷新令牌: " + refreshTokenValue); + } else { + OAuth2RefreshToken refreshToken = this.tokenStore.readRefreshToken(refreshTokenValue); + if (refreshToken == null) { + throw new InvalidGrantException("无效的刷新令牌: " + refreshTokenValue); + } else { + OAuth2Authentication authentication = this.tokenStore.readAuthenticationForRefreshToken(refreshToken); + if (this.authenticationManager != null && !authentication.isClientOnly()) { + Authentication user = new PreAuthenticatedAuthenticationToken(authentication.getUserAuthentication(), "", authentication.getAuthorities()); + user = this.authenticationManager.authenticate(user); + Object details = authentication.getDetails(); + authentication = new OAuth2Authentication(authentication.getOAuth2Request(), user); + authentication.setDetails(details); + } + + String clientId = authentication.getOAuth2Request().getClientId(); + if (clientId != null && clientId.equals(tokenRequest.getClientId())) { + this.tokenStore.removeAccessTokenUsingRefreshToken(refreshToken); + if (this.isExpired(refreshToken)) { + this.tokenStore.removeRefreshToken(refreshToken); + throw new InvalidTokenException("无效的刷新令牌 (超时): " + refreshToken); + } else { + authentication = this.createRefreshedAuthentication(authentication, tokenRequest); + if (!this.reuseRefreshToken) { + this.tokenStore.removeRefreshToken(refreshToken); + refreshToken = this.createRefreshToken(authentication); + } + + OAuth2AccessToken accessToken = this.createAccessToken(authentication, refreshToken); + this.tokenStore.storeAccessToken(accessToken, authentication); + if (!this.reuseRefreshToken) { + this.tokenStore.storeRefreshToken(accessToken.getRefreshToken(), authentication); + } + + return accessToken; + } + } else { + throw new InvalidGrantException("Wrong client for this refresh token: " + refreshTokenValue); + } + } + } + } + + @Override + public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { + return this.tokenStore.getAccessToken(authentication); + } + + private OAuth2Authentication createRefreshedAuthentication(OAuth2Authentication authentication, TokenRequest request) { + Set scope = request.getScope(); + OAuth2Request clientAuth = authentication.getOAuth2Request().refresh(request); + if (scope != null && !scope.isEmpty()) { + Set originalScope = clientAuth.getScope(); + if (originalScope == null || !originalScope.containsAll(scope)) { + throw new InvalidScopeException("无法将客户端身份验证的范围缩小到 " + scope + ".", originalScope); + } + + clientAuth = clientAuth.narrowScope(scope); + } + + OAuth2Authentication narrowed = new OAuth2Authentication(clientAuth, authentication.getUserAuthentication()); + return narrowed; + } + + protected boolean isExpired(OAuth2RefreshToken refreshToken) { + if (!(refreshToken instanceof ExpiringOAuth2RefreshToken)) { + return false; + } else { + ExpiringOAuth2RefreshToken expiringToken = (ExpiringOAuth2RefreshToken) refreshToken; + return expiringToken.getExpiration() == null || System.currentTimeMillis() > expiringToken.getExpiration().getTime(); + } + } + + @Override + public OAuth2AccessToken readAccessToken(String accessToken) { + return this.tokenStore.readAccessToken(accessToken); + } + + @Override + public OAuth2Authentication loadAuthentication(String accessTokenValue) throws AuthenticationException, InvalidTokenException { + OAuth2AccessToken accessToken = this.tokenStore.readAccessToken(accessTokenValue); + if (accessToken == null) { + throw new InvalidTokenException("无效的访问令牌: " + accessTokenValue); + } else if (accessToken.isExpired()) { + this.tokenStore.removeAccessToken(accessToken); + throw new InvalidTokenException("访问令牌超时: " + accessTokenValue); + } else { + OAuth2Authentication result = this.tokenStore.readAuthentication(accessToken); + if (result == null) { + throw new InvalidTokenException("无效的访问令牌: " + accessTokenValue); + } else { + if (this.clientDetailsService != null) { + String clientId = result.getOAuth2Request().getClientId(); + + try { + this.clientDetailsService.loadClientByClientId(clientId); + } catch (ClientRegistrationException var6) { + throw new InvalidTokenException("客户端无效: " + clientId, var6); + } + } + + return result; + } + } + } + + public String getClientId(String tokenValue) { + OAuth2Authentication authentication = this.tokenStore.readAuthentication(tokenValue); + if (authentication == null) { + throw new InvalidTokenException("无效的访问令牌: " + tokenValue); + } else { + OAuth2Request clientAuth = authentication.getOAuth2Request(); + if (clientAuth == null) { + throw new InvalidTokenException("无效的访问令牌 (不存在clientId): " + tokenValue); + } else { + return clientAuth.getClientId(); + } + } + } + + @Override + public boolean revokeToken(String tokenValue) { + OAuth2AccessToken accessToken = this.tokenStore.readAccessToken(tokenValue); + if (accessToken == null) { + return false; + } else { + if (accessToken.getRefreshToken() != null) { + this.tokenStore.removeRefreshToken(accessToken.getRefreshToken()); + } + + this.tokenStore.removeAccessToken(accessToken); + return true; + } + } + + private OAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) { + if (!this.isSupportRefreshToken(authentication.getOAuth2Request())) { + return null; + } else { + int validitySeconds = this.getRefreshTokenValiditySeconds(authentication.getOAuth2Request()); + String value = UUID.randomUUID().toString(); + return (OAuth2RefreshToken) (validitySeconds > 0 ? new DefaultExpiringOAuth2RefreshToken(value, new Date(System.currentTimeMillis() + (long) validitySeconds * 1000L)) : new DefaultOAuth2RefreshToken(value)); + } + } + + private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, OAuth2RefreshToken refreshToken) { + DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString()); + int validitySeconds = this.getAccessTokenValiditySeconds(authentication.getOAuth2Request()); + if (validitySeconds > 0) { + token.setExpiration(new Date(System.currentTimeMillis() + (long) validitySeconds * 1000L)); + } + + token.setRefreshToken(refreshToken); + token.setScope(authentication.getOAuth2Request().getScope()); + return (OAuth2AccessToken) (this.accessTokenEnhancer != null ? this.accessTokenEnhancer.enhance(token, authentication) : token); + } + + protected int getAccessTokenValiditySeconds(OAuth2Request clientAuth) { + if (this.clientDetailsService != null) { + ClientDetails client = this.clientDetailsService.loadClientByClientId(clientAuth.getClientId()); + Integer validity = client.getAccessTokenValiditySeconds(); + if (validity != null) { + return validity; + } + } + + return this.accessTokenValiditySeconds; + } + + protected int getRefreshTokenValiditySeconds(OAuth2Request clientAuth) { + if (this.clientDetailsService != null) { + ClientDetails client = this.clientDetailsService.loadClientByClientId(clientAuth.getClientId()); + Integer validity = client.getRefreshTokenValiditySeconds(); + if (validity != null) { + return validity; + } + } + + return this.refreshTokenValiditySeconds; + } + + protected boolean isSupportRefreshToken(OAuth2Request clientAuth) { + if (this.clientDetailsService != null) { + ClientDetails client = this.clientDetailsService.loadClientByClientId(clientAuth.getClientId()); + return client.getAuthorizedGrantTypes().contains("refresh_token"); + } else { + return this.supportRefreshToken; + } + } + + public void setTokenEnhancer(TokenEnhancer accessTokenEnhancer) { + this.accessTokenEnhancer = accessTokenEnhancer; + } + + public void setRefreshTokenValiditySeconds(int refreshTokenValiditySeconds) { + this.refreshTokenValiditySeconds = refreshTokenValiditySeconds; + } + + public void setAccessTokenValiditySeconds(int accessTokenValiditySeconds) { + this.accessTokenValiditySeconds = accessTokenValiditySeconds; + } + + public void setSupportRefreshToken(boolean supportRefreshToken) { + this.supportRefreshToken = supportRefreshToken; + } + + public void setReuseRefreshToken(boolean reuseRefreshToken) { + this.reuseRefreshToken = reuseRefreshToken; + } + + public void setTokenStore(TokenStore tokenStore) { + this.tokenStore = tokenStore; + } + + public void setAuthenticationManager(AuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + } + + public void setClientDetailsService(ClientDetailsService clientDetailsService) { + this.clientDetailsService = clientDetailsService; + } + +} diff --git a/service-oauth-client/src/main/resources/mybatis/mapper/oauthclient-mapper.xml b/login-oauth2-server/src/main/resources/mybatis/mapper/IOAuth2ClientDao.xml similarity index 70% rename from service-oauth-client/src/main/resources/mybatis/mapper/oauthclient-mapper.xml rename to login-oauth2-server/src/main/resources/mybatis/mapper/IOAuth2ClientDao.xml index 25f3c552..55c5b18f 100644 --- a/service-oauth-client/src/main/resources/mybatis/mapper/oauthclient-mapper.xml +++ b/login-oauth2-server/src/main/resources/mybatis/mapper/IOAuth2ClientDao.xml @@ -1,17 +1,17 @@ - + - + - + @@ -31,6 +31,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CREATE TABLE IF NOT EXISTS `oauth_client_details` ( + `client_id` varchar(48) NOT NULL, + `resource_ids` varchar(255) DEFAULT NULL, + `client_secret` varchar(255) DEFAULT NULL, + `scope` varchar(255) DEFAULT NULL, + `authorized_grant_types` varchar(255) DEFAULT NULL, + `web_server_redirect_uri` varchar(255) DEFAULT NULL, + `authorities` varchar(255) DEFAULT NULL, + `access_token_validity` int(11) DEFAULT NULL, + `refresh_token_validity` int(11) DEFAULT NULL, + `additional_information` varchar(4096) DEFAULT NULL, + `autoapprove` varchar(256) DEFAULT NULL, + `client_name` varchar(255) DEFAULT NULL, + `menu_id` char(36) DEFAULT NULL COMMENT '菜单ID', + `environment` varchar(10) DEFAULT 'formal' COMMENT '系统环境', + `system_type` varchar(10) DEFAULT 'within' COMMENT '系统类型', + `system_state` varchar(10) DEFAULT NULL COMMENT '系统状态', + `expire_time` varchar(10) DEFAULT NULL COMMENT '系统到期时间', + `system_summary` text COMMENT '系统介绍', + `system_icon` varchar(255) DEFAULT NULL COMMENT '系统图标', + `gmt_create` datetime DEFAULT NULL, + `creator` bigint(20) DEFAULT NULL, + `gmt_modified` datetime DEFAULT NULL, + `modifier` bigint(20) DEFAULT NULL, + `is_delete` int(2) DEFAULT '0', + PRIMARY KEY (`client_id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + INSERT INTO oauth_client_details( @@ -165,7 +224,7 @@ - SELECT t1.client_id, t1.client_name, @@ -185,17 +244,9 @@ t1.expire_time, t1.system_summary, t1.system_icon, - LEFT(t1.gmt_create, 10) gmt_create, - t2.menu_id, - t2.menu_name + LEFT(t1.gmt_create, 10) gmt_create FROM oauth_client_details t1 - LEFT JOIN - sys_menu t2 - ON - t1.menu_id = t2.menu_id - AND - t2.is_delete = 0 WHERE t1.is_delete = 0 @@ -236,7 +287,7 @@ - SELECT t1.client_id, t1.client_name, @@ -249,7 +300,7 @@ - SELECT t1.client_id, t1.client_name, @@ -298,7 +349,7 @@ - SELECT t1.client_id, t1.client_name, @@ -317,7 +368,12 @@ t1.system_state, t1.expire_time, t1.system_summary, - t1.system_icon + t1.system_icon, + t1.gmt_create, + t1.creator, + t1.gmt_modified, + t1.modifier, + t1.is_delete FROM oauth_client_details t1 WHERE @@ -329,11 +385,11 @@ - + UPDATE oauth_client_details SET - menu_id = null + menu_id = #{menuId} WHERE client_id = #{clientId} diff --git a/service-oauth-client/src/main/resources/templates/oauth/client/list.html b/login-oauth2-server/src/main/resources/templates/oauth2client/list.html similarity index 72% rename from service-oauth-client/src/main/resources/templates/oauth/client/list.html rename to login-oauth2-server/src/main/resources/templates/oauth2client/list.html index 689f23e0..31ee1b73 100644 --- a/service-oauth-client/src/main/resources/templates/oauth/client/list.html +++ b/login-oauth2-server/src/main/resources/templates/oauth2client/list.html @@ -1,7 +1,7 @@ - + - + @@ -87,7 +87,7 @@ table.render({ elem: '#dataTable', id: 'dataTable', - url: top.restAjax.path('api/oauthclient/listpageoauthclient', []), + url: top.restAjax.path('api/oauth2client/listpage', []), width: admin.screen() > 1 ? '100%' : '', height: $win.height() - 90, limit: 20, @@ -97,84 +97,86 @@ pageName: 'page', limitName: 'rows' }, - cols: [[ - {type:'checkbox', fixed: 'left'}, - {field:'rowNum', width:80, title: '序号', fixed: 'left', align:'center', templet: '#rowNum'}, - {field:'clientName', width:250, title: '客户端名称', align:'center',}, - {field:'scope', width:60, title: '范围', align:'center', - templet: function(item) { - var value; - switch (item.scope) { - case 'all': - value = '全部'; - break; - case 'read': - value = '只读'; - break; - case 'write': - value = '只写'; - break; - default: - value = '无'; + cols: [ + [ + {type:'checkbox', fixed: 'left'}, + {field:'rowNum', width:80, title: '序号', fixed: 'left', align:'center', templet: '#rowNum'}, + {field:'clientName', width:250, title: '客户端名称', align:'center',}, + {field:'scope', width:60, title: '范围', align:'center', + templet: function(item) { + var value; + switch (item.scope) { + case 'all': + value = '全部'; + break; + case 'read': + value = '只读'; + break; + case 'write': + value = '只写'; + break; + default: + value = '无'; + } + return value; } - return value; - } - }, - {field:'authorizedGrantTypes', width:200, title: '授权模式', align:'center', - templet: function(item) { - return item.authorizedGrantTypes.replace(/(authorization_code)/g, '授权码模式') - .replace(/(password)/g, '密码模式') - .replace(/(client_credentials)/, '客户端模式') - .replace(/(implicit)/g, '简单模式') - .replace(/refresh_token/g, '刷新'); - } - }, - {field:'webServerRedirectUri', width: 300, title: '重定向链接', align:'center', - templet: function(item) { - return ''+ item.webServerRedirectUri +''; - } - }, - {field:'authorities', width:60, title: '权限', align:'center', - templet: function(item) { - var value; - switch (item.authorities) { - case 'all': - value = '全部'; - break; - default: - value = '无'; + }, + {field:'authorizedGrantTypes', width:200, title: '授权模式', align:'center', + templet: function(item) { + return item.authorizedGrantTypes.replace(/(authorization_code)/g, '授权码模式') + .replace(/(password)/g, '密码模式') + .replace(/(client_credentials)/, '客户端模式') + .replace(/(implicit)/g, '简单模式') + .replace(/refresh_token/g, '刷新'); } - return value; - } - }, - {field:'accessTokenValidity', width:120, title: '访问令牌时效', align:'center',}, - {field:'refreshTokenValidity', width:120, title: '刷新令牌时效', align:'center',}, - {field:'autoapprove', width:100, title: '自动授权', align:'center', - templet: function(item) { - var value; - switch (item.autoapprove) { - case 'true': - value = '启用'; - break; - case 'false': - value = '关闭'; - break; - default: - value = '无'; + }, + {field:'webServerRedirectUri', width: 300, title: '重定向链接', align:'center', + templet: function(item) { + return ''+ item.webServerRedirectUri +''; } - return value; - } - }, - {field:'menuName', width:200, title: '菜单名称', align:'center', - templet: function(item) { - if(item.menuName == null || item.menuName == '') { - return '未绑定'; + }, + {field:'authorities', width:60, title: '权限', align:'center', + templet: function(item) { + var value; + switch (item.authorities) { + case 'all': + value = '全部'; + break; + default: + value = '无'; + } + return value; } - return item.menuName; - } - }, - {field:'bindMenu', width:120, title: '绑定菜单', align:'center', fixed: 'right', templet: '#bindMenu'} - ]], + }, + {field:'accessTokenValidity', width:120, title: '访问令牌时效', align:'center',}, + {field:'refreshTokenValidity', width:120, title: '刷新令牌时效', align:'center',}, + {field:'autoapprove', width:100, title: '自动授权', align:'center', + templet: function(item) { + var value; + switch (item.autoapprove) { + case 'true': + value = '启用'; + break; + case 'false': + value = '关闭'; + break; + default: + value = '无'; + } + return value; + } + }, + {field:'menuName', width:200, title: '菜单名称', align:'center', + templet: function(item) { + if(item.menuName == null || item.menuName == '') { + return '未绑定'; + } + return item.menuName; + } + }, + {field:'bindMenu', width:120, title: '绑定菜单', align:'center', fixed: 'right', templet: '#bindMenu'} + ] + ], page: true, parseData: function(data) { return { @@ -189,7 +191,7 @@ // 重载表格 function reloadTable(currentPage) { table.reload('dataTable', { - url: top.restAjax.path('api/oauthclient/listpageoauthclient', []), + url: top.restAjax.path('api/oauth2client/listpage', []), where: { keywords: $('#keywords').val(), startTime: $('#startTime').val(), @@ -222,7 +224,7 @@ yes: function (index) { top.dialog.close(index); var layIndex; - top.restAjax.delete(top.restAjax.path('api/oauthclient/removeoauthclient/{ids}', [ids]), {}, null, function (code, data) { + top.restAjax.delete(top.restAjax.path('api/oauth2client/remove/{ids}', [ids]), {}, null, function (code, data) { top.dialog.msg(top.dataMessage.deleteSuccess, {time: 1000}, function () { reloadTable(); }); @@ -256,7 +258,7 @@ yes: function (index) { top.dialog.close(index); var layIndex; - top.restAjax.put(top.restAjax.path('api/oauthclient/updateoauthclientmenu/{clientId}', [clientId]), params, null, function (code, data) { + top.restAjax.put(top.restAjax.path('api/oauth2client/update-menu-init/{clientId}', [clientId]), params, null, function (code, data) { top.dialog.msg(successMessage, {time: 1000}); reloadTable(); }, function (code, data) { @@ -301,7 +303,7 @@ yes: function (index) { top.dialog.close(index); var layIndex; - top.restAjax.put(top.restAjax.path('api/oauthclient/updateclientmenuempty/{clientId}', [clientId]), {}, null, function (code, data) { + top.restAjax.put(top.restAjax.path('api/oauth2client/update-menu-empty/{clientId}', [clientId]), {}, null, function (code, data) { top.dialog.msg('解绑成功', {time: 1000}); reloadTable(); }, function (code, data) { @@ -341,7 +343,7 @@ area: ['100%', '100%'], shadeClose: true, anim: 2, - content: top.restAjax.path('route/system/oauthclient/save.html', []), + content: top.restAjax.path('route/oauth2client/save', []), end: function() { reloadTable(); } @@ -359,7 +361,7 @@ area: ['100%', '100%'], shadeClose: true, anim: 2, - content: top.restAjax.path('route/system/oauthclient/update.html?clientId={id}', [checkDatas[0].clientId]), + content: top.restAjax.path('route/oauth2client/update?clientId={clientId}', [checkDatas[0].clientId]), end: function() { reloadTable(); } @@ -378,8 +380,6 @@ } removeData(ids); } - } else if(layEvent === 'LAYTABLE_EXPORT') { - var exportColumns = common.listTableExportColumns('dataTable'); } }); table.on('tool(dataTable)', function(obj) { diff --git a/service-oauth-client/src/main/resources/templates/oauth/client/save.html b/login-oauth2-server/src/main/resources/templates/oauth2client/save.html similarity index 98% rename from service-oauth-client/src/main/resources/templates/oauth/client/save.html rename to login-oauth2-server/src/main/resources/templates/oauth2client/save.html index 89b26275..b5c7e703 100644 --- a/service-oauth-client/src/main/resources/templates/oauth/client/save.html +++ b/login-oauth2-server/src/main/resources/templates/oauth2client/save.html @@ -1,7 +1,7 @@ - + - + @@ -138,7 +138,7 @@ {{# for(var i = 0, item = files[i]; item = files[i++];) { }}
- + @@ -204,7 +204,7 @@ return; } - top.restAjax.get(top.restAjax.path('api/file/list', []), { + top.restAjax.get(top.restAjax.path('api/file/listfilebyfileid', []), { ids: ids }, null, function(code, data) { refreshDownloadTemplet(fileName, data); diff --git a/service-oauth-client/src/main/resources/templates/oauth/client/update.html b/login-oauth2-server/src/main/resources/templates/oauth2client/update.html similarity index 98% rename from service-oauth-client/src/main/resources/templates/oauth/client/update.html rename to login-oauth2-server/src/main/resources/templates/oauth2client/update.html index 400007ac..b0b4c19d 100644 --- a/service-oauth-client/src/main/resources/templates/oauth/client/update.html +++ b/login-oauth2-server/src/main/resources/templates/oauth2client/update.html @@ -1,7 +1,7 @@ - + - + @@ -138,7 +138,7 @@ {{# for(var i = 0, item = files[i]; item = files[i++];) { }}
- + @@ -205,7 +205,7 @@ return; } - top.restAjax.get(top.restAjax.path('api/file/list', []), { + top.restAjax.get(top.restAjax.path('api/file/listfilebyfileid', []), { ids: ids }, null, function(code, data) { refreshDownloadTemplet(fileName, data); diff --git a/pom.xml b/pom.xml index a4ec36cc..f80317a8 100644 --- a/pom.xml +++ b/pom.xml @@ -22,12 +22,12 @@ module-dictionary service-permission service-menu - service-oauth-client service-group service-position login-base login-app login-wechat + login-oauth2-server basic-properties module-article module-wechat @@ -38,12 +38,12 @@ module-map module-activiti module-instant-message - login-oauth pom 5.2.8.RELEASE + 5.5.2 2.3.3.RELEASE 1.2.24 20210307 @@ -132,20 +132,30 @@ spring-aop ${spring.version} + + org.springframework + spring-expression + ${spring.version} + org.springframework.security spring-security-config - ${spring.version} + ${spring-security.version} org.springframework.security spring-security-web - ${spring.version} + ${spring-security.version} - org.springframework - spring-expression - ${spring.version} + org.springframework.security + spring-security-oauth2-core + ${spring-security.version} + + + org.springframework.security + spring-security-oauth2-jose + ${spring-security.version} diff --git a/service-oauth-client/pom.xml b/service-oauth-client/pom.xml deleted file mode 100644 index 4d167e88..00000000 --- a/service-oauth-client/pom.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - wg-basic - ink.wgink - 1.0-SNAPSHOT - - 4.0.0 - - service-oauth-client - oauth客户端业务 - - - - ink.wgink - common - 1.0-SNAPSHOT - - - - \ No newline at end of file diff --git a/service-oauth-client/src/main/java/ink/wgink/module/oauth/client/controller/api/OauthClientController.java b/service-oauth-client/src/main/java/ink/wgink/module/oauth/client/controller/api/OauthClientController.java deleted file mode 100644 index d8fea0a4..00000000 --- a/service-oauth-client/src/main/java/ink/wgink/module/oauth/client/controller/api/OauthClientController.java +++ /dev/null @@ -1,239 +0,0 @@ -package ink.wgink.module.oauth.client.controller.api; - -import ink.wgink.common.base.DefaultBaseController; -import ink.wgink.exceptions.ParamsException; -import ink.wgink.interfaces.consts.ISystemConstant; -import ink.wgink.pojo.ListPage; -import ink.wgink.pojo.dtos.oauth.client.OauthClientDTO; -import ink.wgink.pojo.result.ErrorResult; -import ink.wgink.pojo.result.SuccessResult; -import ink.wgink.pojo.result.SuccessResultList; -import ink.wgink.module.oauth.client.pojo.vos.OauthClientVO; -import ink.wgink.module.oauth.client.service.IOauthClientService; -import ink.wgink.util.AesUtil; -import io.swagger.annotations.*; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.web.bind.annotation.*; - -import java.io.UnsupportedEncodingException; -import java.util.List; -import java.util.Map; - -/** - * @ClassName: OauthClientController - * @Description: Oauth客户端 - * @Author: WangGeng - * @Date: 2019/3/12 11:15 AM - * @Version: 1.0 - **/ -@Api(tags = ISystemConstant.API_TAGS_SYSTEM_PREFIX + "Oauth客户端") -@RestController -@RequestMapping(ISystemConstant.API_PREFIX + "/oauthclient") -public class OauthClientController extends DefaultBaseController { - - @Autowired - private IOauthClientService oauthClientService; - @Autowired - private PasswordEncoder passwordEncoder; - - @ApiOperation(value = "Oauth客户端新增", notes = "Oauth客户端新增接口") - @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) - @PostMapping("save") - public SuccessResult save(@RequestBody OauthClientVO oauthClientVO) throws UnsupportedEncodingException { - Map params = getParams(); - if (StringUtils.isBlank(oauthClientVO.getClientId())) { - throw new ParamsException("clientId不能为空"); - } - params.put("clientId", oauthClientVO.getClientId()); - - if (StringUtils.isBlank(oauthClientVO.getClientSecret())) { - throw new ParamsException("clientSecret不能为空"); - } - if (!StringUtils.equals(oauthClientVO.getClientSecret(), - Base64.encodeBase64String( - AesUtil.aesEncoder( - IOauthClientService.OAUTH_CLIENT_RULE, oauthClientVO.getClientId() - ).getBytes("UTF-8") - ))) { - throw new ParamsException("clientId与clientSecret不匹配"); - } - params.put("clientSecret", passwordEncoder.encode(oauthClientVO.getClientSecret())); - checkParams(oauthClientVO, params); - - return oauthClientService.save(params); - } - - @ApiOperation(value = "Oauth客户端删除", notes = "Oauth客户端删除接口") - @ApiImplicitParams({ - @ApiImplicitParam(name = "ids", value = "Oauth客户端ID列表,用下划线分隔", paramType = "path", example = "1_2_3") - }) - @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) - @DeleteMapping("remove/{ids}") - public SuccessResult remove(@PathVariable("ids") String ids) { - Map params = getParams(); - params.put("secretIds", ids); - return oauthClientService.remove(params); - } - - @ApiOperation(value = "Oauth客户端修改", notes = "Oauth客户端修改接口") - @ApiImplicitParams({ - @ApiImplicitParam(name = "clientId", value = "Oauth客户端ID", paramType = "path") - }) - @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) - @PutMapping("update/{clientId}") - public SuccessResult update(@PathVariable("clientId") String clientId, - @RequestBody OauthClientVO oauthClientVO) { - Map params = getParams(); - params.put("clientId", clientId); - checkParams(oauthClientVO, params); - return oauthClientService.update(params); - } - - /** - * 校验参数 - * - * @param oauthClientVO - * @param params - * @throws ParamsException - */ - private void checkParams(OauthClientVO oauthClientVO, Map params) { - if (StringUtils.isBlank(oauthClientVO.getClientName())) { - throw new ParamsException("客户端名称不能为空"); - } - params.put("clientName", oauthClientVO.getClientName()); - - if (StringUtils.isBlank(oauthClientVO.getScope())) { - throw new ParamsException("范围不能为空"); - } - params.put("scope", oauthClientVO.getScope()); - - if (StringUtils.isBlank(oauthClientVO.getAuthorizedGrantTypes())) { - throw new ParamsException("授权类型不能为空"); - } - params.put("authorizedGrantTypes", oauthClientVO.getAuthorizedGrantTypes()); - - if (StringUtils.isBlank(oauthClientVO.getAuthorities())) { - throw new ParamsException("授权不能为空"); - } - params.put("authorities", oauthClientVO.getAuthorities()); - - if (StringUtils.isBlank(oauthClientVO.getWebServerRedirectUri())) { - throw new ParamsException("重定向链接不能为空"); - } - params.put("webServerRedirectUri", oauthClientVO.getWebServerRedirectUri()); - - if (oauthClientVO.getAccessTokenValidity() == null) { - throw new ParamsException("访问令牌时效不能为空"); - } - params.put("accessTokenValidity", oauthClientVO.getAccessTokenValidity()); - - if (oauthClientVO.getRefreshTokenValidity() == null) { - throw new ParamsException("刷新令牌时效不能为空"); - } - params.put("refreshTokenValidity", oauthClientVO.getRefreshTokenValidity()); - - if (StringUtils.isBlank(oauthClientVO.getAutoapprove())) { - params.put("autoapprove", "true"); - } else { - params.put("autoapprove", oauthClientVO.getAutoapprove()); - } - - if (StringUtils.isBlank(oauthClientVO.getEnvironment())) { - throw new ParamsException("系统环境不能为空"); - } else { - params.put("environment", oauthClientVO.getEnvironment()); - } - - if (StringUtils.isBlank(oauthClientVO.getSystemType())) { - throw new ParamsException("系统类型不能为空"); - } else { - params.put("systemType", oauthClientVO.getSystemType()); - } - - if (StringUtils.equals(oauthClientVO.getSystemType(), IOauthClientService.OAUTH_CLIENT_SYSTEM_TYPE_THIRD)) { - if (StringUtils.isBlank(oauthClientVO.getSystemState())) { - throw new ParamsException("系统状态不能为空"); - } else { - params.put("systemState", oauthClientVO.getSystemState()); - } - if (StringUtils.isBlank(oauthClientVO.getExpireTime())) { - throw new ParamsException("系统到期时间不能为空"); - } else { - params.put("expireTime", oauthClientVO.getExpireTime()); - } - } - params.put("systemSummary", oauthClientVO.getSystemSummary()); - params.put("systemIcon", oauthClientVO.getSystemIcon()); - } - - @ApiOperation(value = "easyui Oauth客户端列表", notes = "easyui Oauth客户端列表列表接口") - @ApiImplicitParams({ - @ApiImplicitParam(name = "page", value = "当前页码", paramType = "query", dataType = "int", defaultValue = "1"), - @ApiImplicitParam(name = "rows", value = "显示数量", paramType = "query", dataType = "int", defaultValue = "20"), - @ApiImplicitParam(name = "keywords", value = "关键字", paramType = "query", dataType = "String"), - @ApiImplicitParam(name = "startTime", value = "开始时间", paramType = "query", dataType = "String"), - @ApiImplicitParam(name = "endTime", value = "结束时间", paramType = "query", dataType = "String") - }) - @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) - @GetMapping("listpage") - public SuccessResultList> listPage(ListPage page) { - Map params = requestParams(); - page.setParams(params); - return oauthClientService.listPage(page); - } - - @ApiOperation(value = "Oauth客户端列表", notes = "Oauth客户端列表列表接口") - @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) - @GetMapping("list") - public List list() { - Map params = requestParams(); - return oauthClientService.list(params); - } - - @ApiOperation(value = "Oauth客户端详情", notes = "Oauth客户端详情接口") - @ApiImplicitParams({ - @ApiImplicitParam(name = "clientId", value = "Oauth客户端ID", paramType = "path") - }) - @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) - @GetMapping("get/{clientId}") - public OauthClientDTO get(@PathVariable("clientId") String clientId) throws UnsupportedEncodingException { - Map params = requestParams(); - params.put("clientId", clientId); - return oauthClientService.get(params); - } - - @ApiOperation(value = "Oauth客户端绑定菜单", notes = "Oauth客户端绑定菜单接口,自动创建根节点菜单") - @ApiImplicitParams({ - @ApiImplicitParam(name = "clientId", value = "Oauth客户端ID", paramType = "path") - }) - @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) - @PutMapping("updatemenu/{clientId}") - public SuccessResult updateMenu(@PathVariable("clientId") String clientId, @RequestBody Map params) { - params.put("clientId", clientId); - return oauthClientService.updateOauthClientMenu(params); - } - - @ApiOperation(value = "Oauth客户端初始化数据", notes = "Oauth客户端初始化数据接口") - @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) - @GetMapping("getinitclient") - public OauthClientDTO getInitClient() throws Exception { - Map params = getParams(); - return oauthClientService.getInitClient(params); - } - - @ApiOperation(value = "清除客户端菜单", notes = "清除客户端菜单菜单") - @ApiImplicitParams({ - @ApiImplicitParam(name = "clientId", value = "Oauth客户端ID", paramType = "path") - }) - @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) - @PutMapping("updateclientmenuempty/{clientId}") - public SuccessResult updateClientMenuEmpty(@PathVariable("clientId") String clientId) { - Map params = getParams(); - params.put("clientId", clientId); - return oauthClientService.updateClientMenuEmpty(params); - } - -} diff --git a/service-oauth-client/src/main/java/ink/wgink/module/oauth/client/service/IOauthClientService.java b/service-oauth-client/src/main/java/ink/wgink/module/oauth/client/service/IOauthClientService.java deleted file mode 100644 index 2d7b4c3f..00000000 --- a/service-oauth-client/src/main/java/ink/wgink/module/oauth/client/service/IOauthClientService.java +++ /dev/null @@ -1,130 +0,0 @@ -package ink.wgink.module.oauth.client.service; - -import ink.wgink.pojo.ListPage; -import ink.wgink.pojo.dtos.oauth.client.OauthClientDTO; -import ink.wgink.pojo.dtos.oauth.client.OauthClientSimpleDTO; -import ink.wgink.pojo.result.SuccessResult; -import ink.wgink.pojo.result.SuccessResultData; -import ink.wgink.pojo.result.SuccessResultList; - -import java.io.UnsupportedEncodingException; -import java.util.List; -import java.util.Map; - -/** - * @ClassName: IOauthClientService - * @Description: Oauth客户端 - * @Author: WangGeng - * @Date: 2019/3/12 11:40 AM - * @Version: 1.0 - **/ -public interface IOauthClientService { - - /** - * 客户端加密规则 - */ - String OAUTH_CLIENT_RULE = "CMXX_CLIENT"; - String OAUTH_CLIENT_ENVIRONMENT_FORMAL = "formal"; - String OAUTH_CLIENT_ENVIRONMENT_TEST = "test"; - String OAUTH_CLIENT_SYSTEM_TYPE_WITHIN = "within"; - String OAUTH_CLIENT_SYSTEM_TYPE_THIRD = "third"; - String OAUTH_CLIENT_SYSTEM_STATE_NORMAL = "normal"; - String OAUTH_CLIENT_SYSTEM_STATE_LOCKING = "locking"; - - /** - * Oauth客户端新增 - * - * @param params - * @return - */ - SuccessResult save(Map params); - - /** - * Oauth客户端修改 - * - * @param params - * @return - */ - SuccessResult remove(Map params); - - /** - * Oauth客户端修改 - * - * @param params - * @return - */ - SuccessResult update(Map params); - - /** - * easyUI Oauth客户端列表 - * - * @param page - * @return - */ - SuccessResultList> listPage(ListPage page); - - /** - * Oauth客户端列表 - * - * @param params - * @return - */ - List list(Map params); - - /** - * Oauth客户端列表(简单) - * - * @param params - * @return - */ - List listSimple(Map params); - - /** - * Oauth客户端详情 - * - * @param params - * @return - */ - OauthClientDTO get(Map params) throws UnsupportedEncodingException; - - /** - * Oauth客户端初始化信息 - * - * @param params - * @return - */ - OauthClientDTO getInitClient(Map params) throws UnsupportedEncodingException; - - /** - * Oauth客户端更新菜单 - * - * @param params - * @return - */ - SuccessResult updateOauthClientMenu(Map params); - - /** - * Oauth客户端统计 - * - * @param params - * @return - */ - SuccessResultData count(Map params); - - /** - * 清空Oauth客户端菜单 - * - * @param params - * @return - */ - SuccessResult updateClientMenuEmpty(Map params); - - /** - * 获取Oauth - * - * @param clientId - * @return - */ - OauthClientDTO getSimple(String clientId); - -} diff --git a/service-oauth-client/src/main/java/ink/wgink/module/oauth/client/service/impl/OauthClientServiceImpl.java b/service-oauth-client/src/main/java/ink/wgink/module/oauth/client/service/impl/OauthClientServiceImpl.java deleted file mode 100644 index 4f08a169..00000000 --- a/service-oauth-client/src/main/java/ink/wgink/module/oauth/client/service/impl/OauthClientServiceImpl.java +++ /dev/null @@ -1,149 +0,0 @@ -package ink.wgink.module.oauth.client.service.impl; - -import com.github.pagehelper.PageHelper; -import com.github.pagehelper.PageInfo; -import ink.wgink.common.base.DefaultBaseService; -import ink.wgink.exceptions.UpdateException; -import ink.wgink.pojo.ListPage; -import ink.wgink.pojo.dtos.oauth.client.OauthClientDTO; -import ink.wgink.pojo.dtos.oauth.client.OauthClientSimpleDTO; -import ink.wgink.pojo.result.SuccessResult; -import ink.wgink.pojo.result.SuccessResultData; -import ink.wgink.pojo.result.SuccessResultList; -import ink.wgink.module.oauth.client.dao.IOauthClientDao; -import ink.wgink.module.oauth.client.service.IOauthClientService; -import ink.wgink.util.AesUtil; -import ink.wgink.util.UUIDUtil; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.io.UnsupportedEncodingException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * @ClassName: OauthClientServiceImpl - * @Description: Oauth客户端 - * @Author: WangGeng - * @Date: 2019/3/12 11:40 AM - * @Version: 1.0 - **/ -@Service -public class OauthClientServiceImpl extends DefaultBaseService implements IOauthClientService { - - @Autowired - private IOauthClientDao oauthClientDao; - // @Autowired - // private IMenuService menuService; - - @Override - public SuccessResult save(Map params) { - setSaveInfo(params); - oauthClientDao.save(params); - return new SuccessResult(); - } - - @Override - public SuccessResult remove(Map params) { - params.put("secretIds", Arrays.asList(params.get("secretIds").toString().split("_"))); - setUpdateInfo(params); - oauthClientDao.remove(params); - return new SuccessResult(); - } - - @Override - public SuccessResult update(Map params) { - setUpdateInfo(params); - oauthClientDao.update(params); - return new SuccessResult(); - } - - @Override - public SuccessResultList> listPage(ListPage page) { - PageHelper.startPage(page.getPage(), page.getRows()); - List oauthClientDTOs = oauthClientDao.list(page.getParams()); - PageInfo pageInfo = new PageInfo<>(oauthClientDTOs); - return new SuccessResultList<>(oauthClientDTOs, pageInfo.getPageNum(), pageInfo.getTotal()); - } - - @Override - public List list(Map params) { - return oauthClientDao.list(params); - } - - @Override - public List listSimple(Map params) { - return oauthClientDao.listSimple(params); - } - - @Override - public OauthClientDTO get(Map params) throws UnsupportedEncodingException { - OauthClientDTO oauthClientDTO = oauthClientDao.get(params); - oauthClientDTO.setClientSecret(Base64.encodeBase64String(AesUtil.aesEncoder(OAUTH_CLIENT_RULE, oauthClientDTO.getClientId()).getBytes("UTF-8"))); - return oauthClientDTO; - } - - @Override - public OauthClientDTO getInitClient(Map params) throws UnsupportedEncodingException { - OauthClientDTO oauthClientDTO = new OauthClientDTO(); - String clientId = UUIDUtil.get32UUID(); - String clientSecret = Base64.encodeBase64String(AesUtil.aesEncoder(OAUTH_CLIENT_RULE, clientId).getBytes("UTF-8")); - oauthClientDTO.setClientId(clientId); - oauthClientDTO.setClientSecret(clientSecret); - oauthClientDTO.setAccessTokenValidity(7200); - oauthClientDTO.setRefreshTokenValidity(7200); - return oauthClientDTO; - } - - @Override - public synchronized SuccessResult updateOauthClientMenu(Map params) { - OauthClientDTO oauthClientDTO = oauthClientDao.get(params); - if (!StringUtils.isBlank(oauthClientDTO.getMenuId())) { - throw new UpdateException("菜单已经绑定", true); - } - if (params.get("menuId") == null || StringUtils.isBlank(params.get("menuId").toString())) { - LOG.debug("菜单为空,创建菜单"); - // 创建菜单 - Map menuParams = new HashMap<>(16); - menuParams.put("menuParentId", 0); - menuParams.put("menuName", oauthClientDTO.getClientName() + "菜单"); - menuParams.put("apiPrefix", ""); - menuParams.put("resourcePrefix", ""); - menuParams.put("routePrefix", ""); - menuParams.put("menuUrl", "javascript:void(0);"); - menuParams.put("menuType", "1"); - menuParams.put("menuIcon", "fa-icon-color-white fa fa-list"); - menuParams.put("menuOrder", "1"); - menuParams.put("menuStatus", "0"); - setSaveInfo(menuParams); - // menuService.saveMenu(menuParams); - // 绑定菜单 - params.put("menuId", menuParams.get("menuId")); - } - oauthClientDao.update(params); - return new SuccessResult(); - } - - @Override - public SuccessResultData count(Map params) { - Integer oauthClientCount = oauthClientDao.count(params); - return new SuccessResultData<>(oauthClientCount == null ? 0 : oauthClientCount); - } - - @Override - public SuccessResult updateClientMenuEmpty(Map params) { - oauthClientDao.updateMenuEmpty(params); - return new SuccessResult(); - } - - @Override - public OauthClientDTO getSimple(String clientId) { - Map params = getHashMap(2); - params.put("clientId", clientId); - return oauthClientDao.getSimple(params); - } -}