diff --git a/pmapi/pom.xml b/pmapi/pom.xml index 8bb2f6d..ed54cc1 100644 --- a/pmapi/pom.xml +++ b/pmapi/pom.xml @@ -132,6 +132,13 @@ mapstruct 1.5.3.Final + + + com.auth0 + java-jwt + 3.10.3 + + org.mapstruct mapstruct-processor diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/common/model/ZwddTokenUser.java b/pmapi/src/main/java/com/ningdatech/pmapi/common/model/ZwddTokenUser.java new file mode 100644 index 0000000..c3c99c3 --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/common/model/ZwddTokenUser.java @@ -0,0 +1,16 @@ +package com.ningdatech.pmapi.common.model; + +import lombok.Data; + +@Data +public class ZwddTokenUser { + private Long accountId; + + private String employeeCode; + + private String employeeName; + + private String mobile; + + private Long tenantId; +} diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/common/util/JwtTokenUtil.java b/pmapi/src/main/java/com/ningdatech/pmapi/common/util/JwtTokenUtil.java new file mode 100644 index 0000000..61f52b7 --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/common/util/JwtTokenUtil.java @@ -0,0 +1,91 @@ +package com.ningdatech.pmapi.common.util; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.ningdatech.pmapi.common.model.ZwddTokenUser; +import org.apache.commons.lang3.StringUtils; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * @author liuxinxin + * @date 2023/5/4 下午2:34 + */ + +public class JwtTokenUtil { + + private static final String SECRET_KEY = "dbe1cc89019c4c7abd5085bf47a25fb0"; + + private static final String CLAIM_KEY = "content"; + + private static final Integer DEFAULT_EXPIRE_TIME = Integer.valueOf(86400); + + public static String createToken(ZwddTokenUser dingTokenUser) { + return createToken(dingTokenUser, DEFAULT_EXPIRE_TIME); + } + + public static String createToken(ZwddTokenUser dingTokenUser, Integer expireTime) { + if (dingTokenUser == null) { + throw new IllegalArgumentException(""); + } + if (dingTokenUser.getTenantId() == null) { + throw new IllegalArgumentException(""); + } + if (StringUtils.isEmpty(dingTokenUser.getEmployeeCode())) { + throw new IllegalArgumentException(""); + } + if (dingTokenUser.getTenantId() == null) { + throw new IllegalArgumentException(""); + } + return createToken(JSON.toJSONString(dingTokenUser), expireTime); + } + + private static String createToken(String content, Integer expireTime) { + if (StringUtils.isEmpty(content)) { + throw new IllegalArgumentException(""); + } + Map header = new HashMap<>(4); + header.put("alg", "HS256"); + header.put("typ", "JWT"); + Algorithm algorithm = Algorithm.HMAC256(SECRET_KEY); + return JWT.create() + .withHeader(header) + .withClaim("content", content) + .withIssuedAt(new Date()) + .withExpiresAt(new Date(System.currentTimeMillis() + (expireTime.intValue() * 1000))) + .sign(algorithm); + } + + public static boolean verifyToken(String token) { + if (StringUtils.isEmpty(token)) { + throw new IllegalArgumentException("token"); + } + Algorithm algorithm = Algorithm.HMAC256(SECRET_KEY); + JWTVerifier verifier = JWT.require(algorithm).build(); + verifier.verify(token); + return true; + } + + private static String parseJwtString(String token) { + if (StringUtils.isEmpty(token)) { + throw new IllegalArgumentException("token"); + } + Algorithm algorithm = Algorithm.HMAC256(SECRET_KEY); + JWTVerifier verifier = JWT.require(algorithm).build(); + return verifier.verify(token).getClaim("content").asString(); + } + + public static ZwddTokenUser parseJwt(String token) { + String dingUserJson = parseJwtString(token); + if (StringUtils.isEmpty(dingUserJson)) { + return null; + } + ZwddTokenUser dingTokenUser = (ZwddTokenUser) JSONObject.parseObject(dingUserJson, ZwddTokenUser.class); + return dingTokenUser; + } +} diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/user/controller/UserAuthController.java b/pmapi/src/main/java/com/ningdatech/pmapi/user/controller/UserAuthController.java index 1ba09a6..951e0d0 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/user/controller/UserAuthController.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/user/controller/UserAuthController.java @@ -88,4 +88,15 @@ public class UserAuthController { public void agentLogin(@RequestParam(value = "userId", required = true) String userId) { // 不实现任何内容,只是为了出api文档 } + + @PostMapping(value = "/common-login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) + @ApiOperation(value = "公共登陆接口,目前适用于省局跳转登陆") + @ApiImplicitParams({ + @ApiImplicitParam(name = "credential", value = "凭证", required = true, paramType = "form", dataType = "String"), + @ApiImplicitParam(name = "platform", value = "平台 PROVINCIAL_BUREAU,省局", required = true, paramType = "form", dataType = "String") + }) + public void commonLogin(@RequestParam(value = "credential", required = true) String credential + , @RequestParam(value = "platform", required = true) String platform) { + // 不实现任何内容,只是为了出api文档 + } } diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/AuthProperties.java b/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/AuthProperties.java index 938f339..6e3b4dc 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/AuthProperties.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/AuthProperties.java @@ -34,6 +34,11 @@ public class AuthProperties { */ private String agentLoginUrl; + /** + * 跳转登陆接口(目前只有省局跳转) + */ + private String commonLoginUrl; + private String logoutUrl; private List ignoreAuthUrls; diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/WebSecurityConfig.java b/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/WebSecurityConfig.java index 9d88156..1ef9546 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/WebSecurityConfig.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/WebSecurityConfig.java @@ -5,6 +5,7 @@ import com.ningdatech.basic.util.StrPool; import com.ningdatech.pmapi.common.constant.BizConst; import com.ningdatech.pmapi.common.constant.CommonConst; import com.ningdatech.pmapi.user.security.auth.agent.AgentAuthSecurityConfig; +import com.ningdatech.pmapi.user.security.auth.common.CommonAuthSecurityConfig; import com.ningdatech.pmapi.user.security.auth.credential.CredentialAuthSecurityConfig; import com.ningdatech.pmapi.user.security.auth.handler.DefaultExpiredSessionStrategy; import org.springframework.beans.factory.annotation.Qualifier; @@ -33,15 +34,18 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { private final LogoutSuccessHandler logoutSuccessHandler; private final DefaultExpiredSessionStrategy defaultExpiredSessionStrategy; private final AgentAuthSecurityConfig agentAuthSecurityConfig; + private final CommonAuthSecurityConfig commonAuthSecurityConfig; public WebSecurityConfig(AuthProperties authProperties, CredentialAuthSecurityConfig credentialAuthSecurityConfig, AgentAuthSecurityConfig agentAuthSecurityConfig, + CommonAuthSecurityConfig commonAuthSecurityConfig, @Qualifier(value = "defaultLogoutSuccessHandler") LogoutSuccessHandler logoutSuccessHandler, DefaultExpiredSessionStrategy defaultExpiredSessionStrategy) { this.authProperties = authProperties; this.credentialAuthSecurityConfig = credentialAuthSecurityConfig; this.agentAuthSecurityConfig = agentAuthSecurityConfig; + this.commonAuthSecurityConfig = commonAuthSecurityConfig; this.logoutSuccessHandler = logoutSuccessHandler; this.defaultExpiredSessionStrategy = defaultExpiredSessionStrategy; } @@ -51,7 +55,9 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { assemblerPreAuthUrls(http); http.formLogin() .loginPage(authProperties.getAuthRequireUrl()) - .and().apply(credentialAuthSecurityConfig).and().apply(agentAuthSecurityConfig) + .and().apply(credentialAuthSecurityConfig) + .and().apply(agentAuthSecurityConfig) + .and().apply(commonAuthSecurityConfig) .and() .authorizeRequests().antMatchers(authProperties.getIgnoreAuthUrlsArray()).permitAll().anyRequest() .authenticated().and() diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonAuthFilter.java b/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonAuthFilter.java new file mode 100644 index 0000000..7fe7ce4 --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonAuthFilter.java @@ -0,0 +1,80 @@ +package com.ningdatech.pmapi.user.security.auth.common; + +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.pmapi.user.security.auth.validate.CommonLoginException; +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationServiceException; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.InternalAuthenticationServiceException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * @Author LiuXinXin + * @Date 2020/8/3 8:46 下午 + * @Version 1.0 + **/ +public class CommonAuthFilter extends AbstractAuthenticationProcessingFilter { + + private boolean postOnly = true; + + private static final String CREDENTIAL_PARAMETER = "credential"; + private static final String PLATFORM_PARAMETER = "platform"; + + // ~ Constructors + // =================================================================================================== + + public CommonAuthFilter(String processingUrl) { + super(new AntPathRequestMatcher(processingUrl, HttpMethod.POST.name())); + } + + // ~ Methods + // ======================================================================================================== + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) + throws AuthenticationException { + if (postOnly && !request.getMethod().equals(HttpMethod.POST.name())) { + throw new AuthenticationServiceException("请求方法错误"); + } + String credential = request.getParameter(CREDENTIAL_PARAMETER); + String platform = request.getParameter(PLATFORM_PARAMETER); + if (StringUtils.isBlank(credential)) { + throw new CommonLoginException("凭证 不能为空"); + } + if (StringUtils.isBlank(platform)) { + throw new CommonLoginException("平台 不能为空"); + } + + platform = trim(platform); + credential = trim(credential); + try { + CommonAuthToken authRequest = new CommonAuthToken(platform,credential); + setDetails(request, authRequest); + return this.getAuthenticationManager().authenticate(authRequest); + } catch (AuthenticationException e) { + throw new BadCredentialsException("用户状态"); + } catch (BizException e) { + throw new BadCredentialsException(e.getMessage()); + } catch (Exception e) { + throw new InternalAuthenticationServiceException("授权失败:", e); + } + } + + protected void setDetails(HttpServletRequest request, CommonAuthToken authRequest) { + authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); + } + + private String trim(String trimStr) { + if (StringUtils.isNotBlank(trimStr)) { + return trimStr.trim(); + } + return null; + } +} diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonAuthProvider.java b/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonAuthProvider.java new file mode 100644 index 0000000..8b17cfa --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonAuthProvider.java @@ -0,0 +1,58 @@ +package com.ningdatech.pmapi.user.security.auth.common; + +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.ningdatech.pmapi.common.model.ZwddTokenUser; +import com.ningdatech.pmapi.common.util.JwtTokenUtil; +import com.ningdatech.pmapi.user.security.auth.validate.CommonLoginException; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; + +import java.util.Objects; + +/** + * @Author LiuXinXin + * @Date 2020/8/3 8:55 下午 + * @Version 1.0 + **/ +public class CommonAuthProvider implements AuthenticationProvider { + + private UserDetailsService userDetailsService; + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + if (!(authentication instanceof CommonAuthToken)) { + throw new RuntimeException("CustomAuthProvider 只支持 CustomAuthToken"); + } + CommonAuthToken authenticationToken = (CommonAuthToken) authentication; + // 平台 目前只有省局项管跳转 + String platform = (String) authenticationToken.getPrincipal(); + // 密钥 + String credential = (String) authenticationToken.getCredentials(); + + ZwddTokenUser zwddTokenUser = JwtTokenUtil.parseJwt(credential); + if (Objects.isNull(zwddTokenUser)) { + throw new CommonLoginException("用户信息校验失败"); + } + String employeeCode = zwddTokenUser.getEmployeeCode(); + if (StringUtils.isBlank(employeeCode)) { + throw new CommonLoginException("当前用户尚未创建应用账号,请联系管理员创建账号"); + } + UserDetails user = userDetailsService.loadUserByUsername(zwddTokenUser.getEmployeeCode()); + + // 将用户定义的user放入token中,这样可以在session中查询到所有自定义的用户信息 + return new CommonAuthToken(user, user.getPassword(), user.getAuthorities()); + } + + @Override + public boolean supports(Class authentication) { + return CommonAuthToken.class.isAssignableFrom(authentication); + } + + public void setUserDetailsService(UserDetailsService userDetailsService) { + this.userDetailsService = userDetailsService; + } + +} diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonAuthSecurityConfig.java b/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonAuthSecurityConfig.java new file mode 100644 index 0000000..4097bbf --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonAuthSecurityConfig.java @@ -0,0 +1,55 @@ +package com.ningdatech.pmapi.user.security.auth.common; + +import com.ningdatech.pmapi.user.security.auth.AuthProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.SecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.web.DefaultSecurityFilterChain; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.stereotype.Component; + +/** + * 账号密码登陆的认证配置 + */ +@Component +public class CommonAuthSecurityConfig + extends SecurityConfigurerAdapter { + + @Autowired + @Qualifier(value = "defaultLoginSuccessHandler") + protected AuthenticationSuccessHandler defaultLoginSuccessHandler; + + @Autowired + @Qualifier(value = "defaultLoginFailureHandler") + protected AuthenticationFailureHandler defaultLoginFailureHandler; + + @Autowired + @Qualifier(value = "commonLoginUserDetailService") + private UserDetailsService commonLoginUserDetailService; + + @Autowired + private AuthProperties authProperties; + + private AuthenticationManager authenticationManager; + + @Override + public void configure(HttpSecurity http) throws Exception { + CommonAuthFilter commonAuthFilter = + new CommonAuthFilter(authProperties.getAgentLoginUrl()); + authenticationManager = http.getSharedObject(AuthenticationManager.class); + commonAuthFilter.setAuthenticationManager(authenticationManager); + commonAuthFilter.setAuthenticationSuccessHandler(defaultLoginSuccessHandler); + commonAuthFilter.setAuthenticationFailureHandler(defaultLoginFailureHandler); + + CommonAuthProvider authenticationProvider = new CommonAuthProvider(); + authenticationProvider.setUserDetailsService(commonLoginUserDetailService); + + http.authenticationProvider(authenticationProvider).addFilterAfter(commonAuthFilter, + UsernamePasswordAuthenticationFilter.class); + } +} diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonAuthToken.java b/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonAuthToken.java new file mode 100644 index 0000000..5a041f9 --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonAuthToken.java @@ -0,0 +1,75 @@ +package com.ningdatech.pmapi.user.security.auth.common; + +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.SpringSecurityCoreVersion; + +import java.util.Collection; + +/** + * @Author LiuXinXin + * @Date 2020/8/3 8:52 下午 + * @Version 1.0 + **/ +public class CommonAuthToken extends AbstractAuthenticationToken { + + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + + private final Object principal; + + private final Object credentials; + + /** + * This constructor can be safely used by any code that wishes to create a + * UsernamePasswordAuthenticationToken, as the {@link #isAuthenticated()} will return + * false. + */ + public CommonAuthToken(String principal, String credentials) { + super(null); + this.principal = principal; + this.credentials = credentials; + setAuthenticated(false); + } + + /** + * This constructor should only be used by AuthenticationManager or AuthenticationProvider + * implementations that are satisfied with producing a trusted (i.e. {@link #isAuthenticated()} = true) + * authentication token. + * + * @param principal + * @param authorities + */ + public CommonAuthToken(Object principal, Object credentials, + Collection authorities) { + super(authorities); + this.principal = principal; + this.credentials = credentials; + // must use super, as we override + super.setAuthenticated(true); + } + + @Override + public Object getCredentials() { + return this.credentials; + } + + @Override + public Object getPrincipal() { + return this.principal; + } + + @Override + public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { + if (isAuthenticated) { + throw new IllegalArgumentException( + "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); + } + super.setAuthenticated(false); + } + + @Override + public void eraseCredentials() { + super.eraseCredentials(); + } + +} diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonLoginUserDetailService.java b/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonLoginUserDetailService.java new file mode 100644 index 0000000..3766f7a --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonLoginUserDetailService.java @@ -0,0 +1,49 @@ +package com.ningdatech.pmapi.user.security.auth.common; + + +import com.ningdatech.pmapi.user.manage.UserAuthLoginManage; +import com.ningdatech.pmapi.user.security.auth.model.UserFullInfoDTO; +import com.ningdatech.pmapi.user.security.auth.model.UserInfoDetails; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +import java.util.Objects; + +/** + * @author LiuXinXin + * @date 2022/9/30 上午9:49 + */ + +@Service("commonLoginUserDetailService") +@RequiredArgsConstructor +public class CommonLoginUserDetailService implements UserDetailsService { + + private final UserAuthLoginManage userAuthLoginManage; + + @Override + public UserInfoDetails loadUserByUsername(String username) throws UsernameNotFoundException { + final String employeeCode = username; + UserFullInfoDTO userFullInfoDTO = userAuthLoginManage.getUserFullInfoByEmployeeCode(employeeCode); + + if (Objects.isNull(userFullInfoDTO)) { + throw new UsernameNotFoundException(String.format("%s user not exist", username)); + } + UserInfoDetails userInfoDetails = new UserInfoDetails(); + userInfoDetails.setUserId(userFullInfoDTO.getUserId()); + userInfoDetails.setUsername(userFullInfoDTO.getUsername()); + userInfoDetails.setRealName(userFullInfoDTO.getRealName()); + userInfoDetails.setUserRoleList(userFullInfoDTO.getUserRoleList()); + userInfoDetails.setRegionCode(userFullInfoDTO.getRegionCode()); + userInfoDetails.setRegionLevel(userFullInfoDTO.getRegionLevel()); + userInfoDetails.setIdentifier(userFullInfoDTO.getIdentifier()); + userInfoDetails.setPassword(userFullInfoDTO.getCredential()); + userInfoDetails.setEmployeeCode(userFullInfoDTO.getEmployeeCode()); + userInfoDetails.setOrganizationCode(userFullInfoDTO.getOrganizationCode()); + userInfoDetails.setOrganizationName(userFullInfoDTO.getOrganizationName()); + userInfoDetails.setEmpPosUnitCode(userFullInfoDTO.getEmpPosUnitCode()); + userInfoDetails.setEmpPosUnitName(userFullInfoDTO.getOrganizationName()); + return userInfoDetails; + } +} diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/constants/PlatformTypeEnum.java b/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/constants/PlatformTypeEnum.java new file mode 100644 index 0000000..692c80d --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/constants/PlatformTypeEnum.java @@ -0,0 +1,15 @@ +package com.ningdatech.pmapi.user.security.auth.constants; + +/** + * @author liuxinxin + * @date 2023/5/4 上午10:53 + */ + +public enum PlatformTypeEnum { + + /** + * 省局 + */ + PROVINCIAL_BUREAU + +} diff --git a/pmapi/src/main/resources/security/auth-dev.yml b/pmapi/src/main/resources/security/auth-dev.yml index 1bd9564..aaa4f21 100644 --- a/pmapi/src/main/resources/security/auth-dev.yml +++ b/pmapi/src/main/resources/security/auth-dev.yml @@ -5,6 +5,7 @@ security: password-login-url: /api/v1/user/auth/login agent-login-url: /api/v1/user/auth/agent-login logout-url: /api/v1/user/auth/logout + common-login-url: /api/v1/user/auth/common-login ignore-auth-urls: - /v2/api-docs - /swagger-ui.html @@ -16,6 +17,7 @@ security: - /api/v1/user/auth/invalid-session - /api/v1/user/auth/login/password - /api/v1/user/auth/forget-password + - /api/v1/user/auth/common-login - /doc.html - /ok.html - /open/api/**