瀏覽代碼

Merge remote-tracking branch 'origin/master'

master
PoffyZhang 1 年之前
父節點
當前提交
814b3bc09f
共有 13 個文件被更改,包括 471 次插入1 次删除
  1. +7
    -0
      pmapi/pom.xml
  2. +16
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/common/model/ZwddTokenUser.java
  3. +91
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/common/util/JwtTokenUtil.java
  4. +11
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/user/controller/UserAuthController.java
  5. +5
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/AuthProperties.java
  6. +7
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/WebSecurityConfig.java
  7. +80
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonAuthFilter.java
  8. +58
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonAuthProvider.java
  9. +55
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonAuthSecurityConfig.java
  10. +75
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonAuthToken.java
  11. +49
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/common/CommonLoginUserDetailService.java
  12. +15
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/constants/PlatformTypeEnum.java
  13. +2
    -0
      pmapi/src/main/resources/security/auth-dev.yml

+ 7
- 0
pmapi/pom.xml 查看文件

@@ -132,6 +132,13 @@
<artifactId>mapstruct</artifactId>
<version>1.5.3.Final</version>
</dependency>
<!--引入jwt-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>

<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>


+ 16
- 0
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;
}

+ 91
- 0
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<String, Object> 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;
}
}

+ 11
- 0
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文档
}
}

+ 5
- 0
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<String> ignoreAuthUrls;


+ 7
- 1
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()


+ 80
- 0
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;
}
}

+ 58
- 0
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;
}

}

+ 55
- 0
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<DefaultSecurityFilterChain, HttpSecurity> {

@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);
}
}

+ 75
- 0
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
* <code>UsernamePasswordAuthenticationToken</code>, as the {@link #isAuthenticated()} will return
* <code>false</code>.
*/
public CommonAuthToken(String principal, String credentials) {
super(null);
this.principal = principal;
this.credentials = credentials;
setAuthenticated(false);
}

/**
* This constructor should only be used by <code>AuthenticationManager</code> or <code>AuthenticationProvider</code>
* implementations that are satisfied with producing a trusted (i.e. {@link #isAuthenticated()} = <code>true</code>)
* authentication token.
*
* @param principal
* @param authorities
*/
public CommonAuthToken(Object principal, Object credentials,
Collection<? extends GrantedAuthority> 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();
}

}

+ 49
- 0
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;
}
}

+ 15
- 0
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
}

+ 2
- 0
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/**


Loading…
取消
儲存