diff --git a/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/service/PigxUserDetailsServiceImpl.java b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/service/PigxUserDetailsServiceImpl.java index 7eeffb868..5fe59b7ca 100644 --- a/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/service/PigxUserDetailsServiceImpl.java +++ b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/service/PigxUserDetailsServiceImpl.java @@ -94,15 +94,15 @@ public class PigxUserDetailsServiceImpl implements PigxUserDetailsService { String url = String.format(WX_AUTHORIZATION_CODE_URL , wxSocialConfig.getAppid(), wxSocialConfig.getSecret(), code); String result = restTemplate.getForObject(url, String.class); - log.debug("微信响应报文:{}", result); + log.warn("微信响应报文:{}", result); Object obj = JSONUtil.parseObj(result).get("openid"); if (obj != null) { userInfo = remoteUserService.social(EnumLoginType.WECHAT.getType(), obj.toString()); - } else { - throw new UsernameNotFoundException("获取用户openid失败"); } + } + return getUserDetails(userInfo); } diff --git a/pigx-auth/src/main/resources/bootstrap.yml b/pigx-auth/src/main/resources/bootstrap.yml index 4a98cab0c..aed68dfa4 100644 --- a/pigx-auth/src/main/resources/bootstrap.yml +++ b/pigx-auth/src/main/resources/bootstrap.yml @@ -20,4 +20,4 @@ eureka: prefer-ip-address: true client: service-url: - defaultZone: http://pig:pig@pigx-eureka:1025/eureka/ + defaultZone: http://pig:pig@localhost:1025/eureka/ diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/mobile/MobileAuthenticationEntryPoint.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/mobile/MobileAuthenticationEntryPoint.java new file mode 100644 index 000000000..6397d0127 --- /dev/null +++ b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/mobile/MobileAuthenticationEntryPoint.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.common.security.mobile; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.security.oauth2.provider.error.AbstractOAuth2SecurityExceptionHandler; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.util.StringUtils; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author lengleng + * @date 2018/8/16 + * 手机号登录异常处理 + */ +public class MobileAuthenticationEntryPoint extends AbstractOAuth2SecurityExceptionHandler implements + AuthenticationEntryPoint { + private static final String WWW_AUTHENTICATE = "WWW-Authenticate"; + private static final String SUFFIX = ","; + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) + throws IOException, ServletException { + doHandle(request, response, authException); + } + + @Override + protected ResponseEntity enhanceResponse(ResponseEntity response, Exception exception) { + HttpHeaders headers = response.getHeaders(); + String existing = null; + if (headers.containsKey(WWW_AUTHENTICATE)) { + existing = extractTypePrefix(headers.getFirst("WWW-Authenticate")); + } + StringBuilder builder = new StringBuilder(); + String typeName = OAuth2AccessToken.BEARER_TYPE; + builder.append(typeName + " "); + String realmName = "oauth"; + builder.append("realm=\"" + realmName + "\""); + if (existing != null) { + builder.append(", " + existing); + } + HttpHeaders update = new HttpHeaders(); + update.putAll(response.getHeaders()); + update.set("WWW-Authenticate", builder.toString()); + return new ResponseEntity<>(response.getBody(), update, HttpStatus.EXPECTATION_FAILED); + } + + private String extractTypePrefix(String header) { + String existing = header; + String[] tokens = existing.split(" +"); + if (tokens.length > 1 && !tokens[0].endsWith(SUFFIX)) { + existing = StringUtils.arrayToDelimitedString(tokens, " ").substring(existing.indexOf(" ") + 1); + } + return existing; + } + +} + diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/mobile/MobileAuthenticationFilter.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/mobile/MobileAuthenticationFilter.java index ece485983..257702b8c 100644 --- a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/mobile/MobileAuthenticationFilter.java +++ b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/mobile/MobileAuthenticationFilter.java @@ -21,10 +21,17 @@ import com.pig4cloud.pigx.common.core.constant.SecurityConstants; import lombok.Getter; import lombok.Setter; import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationEventPublisher; import org.springframework.security.authentication.AuthenticationServiceException; +import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; +import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; +import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import javax.servlet.http.HttpServletRequest; @@ -37,6 +44,8 @@ import javax.servlet.http.HttpServletResponse; */ public class MobileAuthenticationFilter extends AbstractAuthenticationProcessingFilter { private static final String SPRING_SECURITY_FORM_MOBILE_KEY = "mobile"; + private AuthenticationEventPublisher eventPublisher = new MobileAuthenticationFilter.NullEventPublisher(); + private AuthenticationEntryPoint authenticationEntryPoint = new MobileAuthenticationEntryPoint(); @Getter @Setter private String mobileParameter = SPRING_SECURITY_FORM_MOBILE_KEY; @@ -68,7 +77,24 @@ public class MobileAuthenticationFilter extends AbstractAuthenticationProcessing setDetails(request, mobileAuthenticationToken); - return this.getAuthenticationManager().authenticate(mobileAuthenticationToken); + try { + return this.getAuthenticationManager().authenticate(mobileAuthenticationToken); + + } catch (Exception failed) { + SecurityContextHolder.clearContext(); + logger.debug("Authentication request failed: " + failed); + + eventPublisher.publishAuthenticationFailure(new BadCredentialsException(failed.getMessage(), failed), + new PreAuthenticatedAuthenticationToken("access-token", "N/A")); + + try { + authenticationEntryPoint.commence(request, response, + new UsernameNotFoundException(failed.getMessage(), failed)); + } catch (Exception e) { + logger.error("authenticationEntryPoint handle error:{}", failed); + } + } + return null; } private String obtainMobile(HttpServletRequest request) { @@ -79,5 +105,15 @@ public class MobileAuthenticationFilter extends AbstractAuthenticationProcessing MobileAuthenticationToken authRequest) { authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); } + + private static final class NullEventPublisher implements AuthenticationEventPublisher { + @Override + public void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication) { + } + + @Override + public void publishAuthenticationSuccess(Authentication authentication) { + } + } } diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/mobile/MobileAuthenticationProvider.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/mobile/MobileAuthenticationProvider.java index c36ac85b6..b43cad2cb 100644 --- a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/mobile/MobileAuthenticationProvider.java +++ b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/mobile/MobileAuthenticationProvider.java @@ -20,10 +20,16 @@ package com.pig4cloud.pigx.common.security.mobile; import com.pig4cloud.pigx.common.security.util.PigxUserDetailsService; import lombok.Getter; import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.support.MessageSourceAccessor; +import org.springframework.security.authentication.AuthenticationEventPublisher; import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.SpringSecurityMessageSource; import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter; /** * @author lengleng @@ -31,7 +37,9 @@ import org.springframework.security.core.userdetails.UserDetails; * 手机登录校验逻辑 * 验证码登录、社交登录 */ +@Slf4j public class MobileAuthenticationProvider implements AuthenticationProvider { + private MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); @Getter @Setter private PigxUserDetailsService userDetailsService; @@ -42,7 +50,14 @@ public class MobileAuthenticationProvider implements AuthenticationProvider { String principal = mobileAuthenticationToken.getPrincipal().toString(); UserDetails userDetails = userDetailsService.loadUserBySocial(principal); + if (userDetails == null) { + log.debug("Authentication failed: no credentials provided"); + throw new BadCredentialsException(messages.getMessage( + "AbstractUserDetailsAuthenticationProvider.noopBindAccount", + "Noop Bind Account")); + + } MobileAuthenticationToken authenticationToken = new MobileAuthenticationToken(userDetails, userDetails.getAuthorities()); authenticationToken.setDetails(mobileAuthenticationToken.getDetails()); diff --git a/pigx-common/pigx-common-security/src/main/resources/org/springframework/security/messages_zh_CN.properties b/pigx-common/pigx-common-security/src/main/resources/org/springframework/security/messages_zh_CN.properties index 8a6bf9187..9666f3e38 100644 --- a/pigx-common/pigx-common-security/src/main/resources/org/springframework/security/messages_zh_CN.properties +++ b/pigx-common/pigx-common-security/src/main/resources/org/springframework/security/messages_zh_CN.properties @@ -20,6 +20,7 @@ AbstractAccessDecisionManager.accessDenied=\u4E0D\u5141\u8BB8\u8BBF\u95EE AbstractLdapAuthenticationProvider.emptyPassword=\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A AbstractSecurityInterceptor.authenticationNotFound=\u672A\u5728SecurityContext\u4E2D\u67E5\u627E\u5230\u8BA4\u8BC1\u5BF9\u8C61 AbstractUserDetailsAuthenticationProvider.badCredentials=\u7528\u6237\u540D\u4E0D\u5B58\u5728\u6216\u8005\u5BC6\u7801\u9519\u8BEF +AbstractUserDetailsAuthenticationProvider.noopBindAccount=\u672A\u7ED1\u5B9A\u767B\u5F55\u8D26\u53F7\uFF0C\u8BF7\u4F7F\u7528\u5BC6\u7801\u767B\u5F55\u540E\u7ED1\u5B9A AbstractUserDetailsAuthenticationProvider.credentialsExpired=\u7528\u6237\u51ED\u8BC1\u5DF2\u8FC7\u671F AbstractUserDetailsAuthenticationProvider.disabled=\u7528\u6237\u672A\u6FC0\u6D3B AbstractUserDetailsAuthenticationProvider.expired=\u7528\u6237\u5E10\u53F7\u5DF2\u8FC7\u671F diff --git a/pigx-config/src/main/resources/bootstrap.yml b/pigx-config/src/main/resources/bootstrap.yml index b175a2426..5564b817f 100644 --- a/pigx-config/src/main/resources/bootstrap.yml +++ b/pigx-config/src/main/resources/bootstrap.yml @@ -19,7 +19,7 @@ eureka: prefer-ip-address: true client: service-url: - defaultZone: http://pig:pig@pigx-eureka:1025/eureka/ + defaultZone: http://pig:pig@localhost:1025/eureka/ # 暴露监控端点 management: diff --git a/pigx-config/src/main/resources/config/application-dev.yml b/pigx-config/src/main/resources/config/application-dev.yml index fe48e9322..de532fa1e 100644 --- a/pigx-config/src/main/resources/config/application-dev.yml +++ b/pigx-config/src/main/resources/config/application-dev.yml @@ -2,7 +2,7 @@ spring: redis: password: - host: redis + host: localhost # 暴露监控端点 management: endpoints: diff --git a/pigx-config/src/main/resources/config/pigx-auth-dev.yml b/pigx-config/src/main/resources/config/pigx-auth-dev.yml index 8f2fb5c50..ad424766e 100644 --- a/pigx-config/src/main/resources/config/pigx-auth-dev.yml +++ b/pigx-config/src/main/resources/config/pigx-auth-dev.yml @@ -12,3 +12,9 @@ social: wx: appid: wxd1678d3f83b1d83a secret: 6ddb043f94da5d2172926abe8533504f + +# 社交登录配置新 +social: + wx: + appid: wxd1678d3f83b1d83a + secret: 6ddb043f94da5d2172926abe8533504f diff --git a/pigx-config/src/main/resources/config/pigx-codegen-dev.yml b/pigx-config/src/main/resources/config/pigx-codegen-dev.yml index 4a91fc002..491bc18b0 100644 --- a/pigx-config/src/main/resources/config/pigx-codegen-dev.yml +++ b/pigx-config/src/main/resources/config/pigx-codegen-dev.yml @@ -13,7 +13,7 @@ spring: driver-class-name: com.mysql.jdbc.Driver username: root password: root - url: jdbc:mysql://mysql:3306/pigx?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false + url: jdbc:mysql://114.116.45.246:13306/pigx?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false jackson: time-zone: GMT+8 date-format: yyyy-MM-dd HH:mm:ss diff --git a/pigx-config/src/main/resources/config/pigx-upms-dev.yml b/pigx-config/src/main/resources/config/pigx-upms-dev.yml index 36ddf3f8a..de28b50f4 100644 --- a/pigx-config/src/main/resources/config/pigx-upms-dev.yml +++ b/pigx-config/src/main/resources/config/pigx-upms-dev.yml @@ -13,7 +13,7 @@ spring: driver-class-name: com.mysql.jdbc.Driver username: root password: root - url: jdbc:mysql://mysql:3306/pigx?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false + url: jdbc:mysql://114.116.45.246:13306/pigx?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false # mybaits 模块配置 mybatis-plus: diff --git a/pigx-gateway/src/main/resources/bootstrap.yml b/pigx-gateway/src/main/resources/bootstrap.yml index 5916dfdb8..aeb0ffd87 100644 --- a/pigx-gateway/src/main/resources/bootstrap.yml +++ b/pigx-gateway/src/main/resources/bootstrap.yml @@ -22,6 +22,6 @@ eureka: prefer-ip-address: true client: service-url: - defaultZone: http://pig:pig@pigx-eureka:1025/eureka/ + defaultZone: http://pig:pig@localhost:1025/eureka/ diff --git a/pigx-upms/pigx-upms-biz/src/main/resources/bootstrap.yml b/pigx-upms/pigx-upms-biz/src/main/resources/bootstrap.yml index ba90e1d06..1dbe02882 100644 --- a/pigx-upms/pigx-upms-biz/src/main/resources/bootstrap.yml +++ b/pigx-upms/pigx-upms-biz/src/main/resources/bootstrap.yml @@ -23,4 +23,4 @@ eureka: prefer-ip-address: true client: service-url: - defaultZone: http://pig:pig@pigx-eureka:1025/eureka/ + defaultZone: http://pig:pig@localhost:1025/eureka/ diff --git a/pigx-visual/pigx-codegen/src/main/resources/bootstrap.yml b/pigx-visual/pigx-codegen/src/main/resources/bootstrap.yml index dcef36826..359f44828 100644 --- a/pigx-visual/pigx-codegen/src/main/resources/bootstrap.yml +++ b/pigx-visual/pigx-codegen/src/main/resources/bootstrap.yml @@ -20,7 +20,7 @@ eureka: prefer-ip-address: true client: service-url: - defaultZone: http://pig:pig@pigx-eureka:1025/eureka/ + defaultZone: http://pig:pig@localhost:1025/eureka/ logging: level: root: debug diff --git a/pigx-visual/pigx-daemon/src/main/resources/bootstrap.yml b/pigx-visual/pigx-daemon/src/main/resources/bootstrap.yml index 88c5cbaf0..da9accb63 100644 --- a/pigx-visual/pigx-daemon/src/main/resources/bootstrap.yml +++ b/pigx-visual/pigx-daemon/src/main/resources/bootstrap.yml @@ -20,4 +20,4 @@ eureka: prefer-ip-address: true client: service-url: - defaultZone: http://pig:pig@pigx-eureka:1025/eureka/ + defaultZone: http://pig:pig@localhost:1025/eureka/ diff --git a/pigx-visual/pigx-monitor/src/main/resources/bootstrap.yml b/pigx-visual/pigx-monitor/src/main/resources/bootstrap.yml index fc2891602..1e29612c9 100644 --- a/pigx-visual/pigx-monitor/src/main/resources/bootstrap.yml +++ b/pigx-visual/pigx-monitor/src/main/resources/bootstrap.yml @@ -20,4 +20,4 @@ eureka: prefer-ip-address: true client: service-url: - defaultZone: http://pig:pig@pigx-eureka:1025/eureka/ + defaultZone: http://pig:pig@localhost:1025/eureka/