From db4e9b7473e01f208b9b0e3e0889b2755b301604 Mon Sep 17 00:00:00 2001 From: zlt2000 Date: Sat, 11 Jul 2020 17:13:38 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84uaa=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E6=8E=88=E6=9D=83=EF=BC=8C=E7=BB=9F=E4=B8=80=E6=8E=88?= =?UTF-8?q?=E6=9D=83=E6=89=80=E6=9C=89=E6=8E=A5=E5=8F=A3=E4=BD=BF=E7=94=A8?= =?UTF-8?q?oauth/token?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zlt-doc/sql/oauth-center.sql | 2 +- ...234\254\345\215\207\347\272\247v4.0.0.sql" | 3 + .../config/AuthorizationServerConfig.java | 10 +- .../central/oauth/config/SecurityConfig.java | 8 +- .../oauth/config/TokenGranterConfig.java | 170 ++++++++++++++++++ .../config/ValidateCodeSecurityConfig.java | 29 --- .../oauth/controller/OAuth2Controller.java | 132 -------------- .../oauth/filter/ValidateCodeFilter.java | 81 --------- .../oauth/granter/MobilePwdGranter.java | 54 ++++++ .../central/oauth/granter/OpenIdGranter.java | 50 ++++++ .../oauth/granter/PwdImgCodeGranter.java | 42 +++++ .../oauth/service/IValidateCodeService.java | 5 +- .../service/impl/ValidateCodeServiceImpl.java | 19 +- 13 files changed, 342 insertions(+), 263 deletions(-) create mode 100644 "zlt-doc/\347\211\210\346\234\254\345\215\207\347\272\247_sql/\346\227\247\347\211\210\346\234\254\345\215\207\347\272\247v4.0.0.sql" create mode 100644 zlt-uaa/src/main/java/com/central/oauth/config/TokenGranterConfig.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/config/ValidateCodeSecurityConfig.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/controller/OAuth2Controller.java delete mode 100644 zlt-uaa/src/main/java/com/central/oauth/filter/ValidateCodeFilter.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/granter/MobilePwdGranter.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/granter/OpenIdGranter.java create mode 100644 zlt-uaa/src/main/java/com/central/oauth/granter/PwdImgCodeGranter.java diff --git a/zlt-doc/sql/oauth-center.sql b/zlt-doc/sql/oauth-center.sql index 0a6e081..a7dcb74 100644 --- a/zlt-doc/sql/oauth-center.sql +++ b/zlt-doc/sql/oauth-center.sql @@ -28,6 +28,6 @@ CREATE TABLE `oauth_client_details` ( -- ---------------------------- -- Records of oauth_client_details -- ---------------------------- -INSERT INTO `oauth_client_details` VALUES (1, 'webApp', NULL, '$2a$10$06msMGYRH8nrm4iVnKFNKOoddB8wOwymVhbUzw/d3ZixD7Nq8ot72', 'webApp', 'app', 'authorization_code,password,refresh_token,client_credentials', NULL, NULL, 3600, NULL, '{}', 'true', NULL, NULL, 'pc端'); +INSERT INTO `oauth_client_details` VALUES (1, 'webApp', NULL, '$2a$10$06msMGYRH8nrm4iVnKFNKOoddB8wOwymVhbUzw/d3ZixD7Nq8ot72', 'webApp', 'app', 'authorization_code,password,refresh_token,client_credentials,implicit,password_code,openId,mobile_password', NULL, NULL, 3600, NULL, '{}', 'true', NULL, NULL, 'pc端'); INSERT INTO `oauth_client_details` VALUES (2, 'app', NULL, '$2a$10$i3F515wEDiB4Gvj9ym9Prui0dasRttEUQ9ink4Wpgb4zEDCAlV8zO', 'app', 'app', 'authorization_code,password,refresh_token', 'http://127.0.0.1:8081/callback.html', NULL, 3600, NULL, '{}', 'true', NULL, NULL, '移动端'); INSERT INTO `oauth_client_details` VALUES (3, 'zlt', NULL, '$2a$10$/o.wuORzVcXaezmYVzwYMuoY7qeWXBALwQmkskXD/7C6rqfCyPrna', 'zlt', 'all', 'authorization_code,password,refresh_token,client_credentials', 'http://127.0.0.1:8080/singleLogin', NULL, 3600, 28800, '{}', 'true', '2018-12-27 00:50:30', '2018-12-27 00:50:30', '第三方应用'); \ No newline at end of file diff --git "a/zlt-doc/\347\211\210\346\234\254\345\215\207\347\272\247_sql/\346\227\247\347\211\210\346\234\254\345\215\207\347\272\247v4.0.0.sql" "b/zlt-doc/\347\211\210\346\234\254\345\215\207\347\272\247_sql/\346\227\247\347\211\210\346\234\254\345\215\207\347\272\247v4.0.0.sql" new file mode 100644 index 0000000..438dd89 --- /dev/null +++ "b/zlt-doc/\347\211\210\346\234\254\345\215\207\347\272\247_sql/\346\227\247\347\211\210\346\234\254\345\215\207\347\272\247v4.0.0.sql" @@ -0,0 +1,3 @@ +------------更新语句 +Use `oauth-center`; +update oauth_client_details set authorized_grant_types = 'authorization_code,password,refresh_token,client_credentials,implicit,password_code,openId,mobile_password' where client_id = 'webApp' \ No newline at end of file diff --git a/zlt-uaa/src/main/java/com/central/oauth/config/AuthorizationServerConfig.java b/zlt-uaa/src/main/java/com/central/oauth/config/AuthorizationServerConfig.java index 55f3b87..240f1e0 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/config/AuthorizationServerConfig.java +++ b/zlt-uaa/src/main/java/com/central/oauth/config/AuthorizationServerConfig.java @@ -11,6 +11,7 @@ import org.springframework.security.oauth2.config.annotation.web.configuration.A 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.TokenGranter; import org.springframework.security.oauth2.provider.code.RandomValueAuthorizationCodeServices; import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.security.oauth2.provider.token.TokenEnhancer; @@ -26,6 +27,9 @@ import java.util.Arrays; * * @author zlt * @date 2018/10/24 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 */ @Configuration @EnableAuthorizationServer @@ -58,6 +62,9 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap @Autowired private RandomValueAuthorizationCodeServices authorizationCodeServices; + @Autowired + private TokenGranter tokenGranter; + /** * 配置身份认证器,配置认证方式,TokenStore,TokenGranter,OAuth2RequestFactory * @param endpoints @@ -78,7 +85,8 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap .authenticationManager(authenticationManager) .userDetailsService(userDetailsService) .authorizationCodeServices(authorizationCodeServices) - .exceptionTranslator(webResponseExceptionTranslator); + .exceptionTranslator(webResponseExceptionTranslator) + .tokenGranter(tokenGranter); } /** diff --git a/zlt-uaa/src/main/java/com/central/oauth/config/SecurityConfig.java b/zlt-uaa/src/main/java/com/central/oauth/config/SecurityConfig.java index c4a4603..aa30874 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/config/SecurityConfig.java +++ b/zlt-uaa/src/main/java/com/central/oauth/config/SecurityConfig.java @@ -33,6 +33,9 @@ import javax.annotation.Resource; * 在WebSecurityConfigurerAdapter不拦截oauth要开放的资源 * * @author zlt + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 */ @Configuration @Import(DefaultPasswordConfig.class) @@ -53,9 +56,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Resource private LogoutHandler oauthLogoutHandler; - @Autowired - private ValidateCodeSecurityConfig validateCodeSecurityConfig; - @Autowired private OpenIdAuthenticationSecurityConfig openIdAuthenticationSecurityConfig; @@ -104,8 +104,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { .addLogoutHandler(oauthLogoutHandler) .clearAuthentication(true) .and() - .apply(validateCodeSecurityConfig) - .and() .apply(openIdAuthenticationSecurityConfig) .and() .apply(mobileAuthenticationSecurityConfig) diff --git a/zlt-uaa/src/main/java/com/central/oauth/config/TokenGranterConfig.java b/zlt-uaa/src/main/java/com/central/oauth/config/TokenGranterConfig.java new file mode 100644 index 0000000..9a33761 --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/config/TokenGranterConfig.java @@ -0,0 +1,170 @@ +package com.central.oauth.config; + +import com.central.oauth.granter.MobilePwdGranter; +import com.central.oauth.granter.OpenIdGranter; +import com.central.oauth.granter.PwdImgCodeGranter; +import com.central.oauth.service.IValidateCodeService; +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.authentication.ProviderManager; +import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.*; +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.AuthorizationServerTokenServices; +import org.springframework.security.oauth2.provider.token.DefaultTokenServices; +import org.springframework.security.oauth2.provider.token.TokenEnhancer; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * token授权模式配置类 + * + * @author zlt + * @date 2020/7/11 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@Configuration +public class TokenGranterConfig { + @Autowired + private ClientDetailsService clientDetailsService; + + @Autowired + private UserDetailsService userDetailsService; + + @Autowired + private AuthenticationManager authenticationManager; + + @Autowired + private TokenStore tokenStore; + + @Autowired(required = false) + private TokenEnhancer tokenEnhancer; + + @Autowired + private IValidateCodeService validateCodeService; + + private AuthorizationCodeServices authorizationCodeServices; + + private boolean reuseRefreshToken = true; + + private AuthorizationServerTokenServices tokenServices; + + private TokenGranter tokenGranter; + + /** + * 授权模式 + */ + @Bean + public TokenGranter tokenGranter() { + if (tokenGranter == null) { + tokenGranter = new TokenGranter() { + private CompositeTokenGranter delegate; + + @Override + public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) { + if (delegate == null) { + delegate = new CompositeTokenGranter(getAllTokenGranters()); + } + return delegate.grant(grantType, tokenRequest); + } + }; + } + return tokenGranter; + } + + /** + * 所有授权模式:默认的5种模式 + 自定义的模式 + */ + private List getAllTokenGranters() { + AuthorizationServerTokenServices tokenServices = tokenServices(); + AuthorizationCodeServices authorizationCodeServices = authorizationCodeServices(); + OAuth2RequestFactory requestFactory = requestFactory(); + //获取默认的授权模式 + List tokenGranters = getDefaultTokenGranters(tokenServices, authorizationCodeServices, requestFactory); + if (authenticationManager != null) { + // 添加密码加图形验证码模式 + tokenGranters.add(new PwdImgCodeGranter(authenticationManager, tokenServices, clientDetailsService, requestFactory, validateCodeService)); + // 添加openId模式 + tokenGranters.add(new OpenIdGranter(authenticationManager, tokenServices, clientDetailsService, requestFactory)); + // 添加手机号加密码授权模式 + tokenGranters.add(new MobilePwdGranter(authenticationManager, tokenServices, clientDetailsService, requestFactory)); + } + return tokenGranters; + } + + /** + * 默认的授权模式 + */ + private List getDefaultTokenGranters(AuthorizationServerTokenServices tokenServices + , AuthorizationCodeServices authorizationCodeServices, OAuth2RequestFactory requestFactory) { + List tokenGranters = new ArrayList<>(); + // 添加授权码模式 + tokenGranters.add(new AuthorizationCodeTokenGranter(tokenServices, authorizationCodeServices, clientDetailsService, requestFactory)); + // 添加刷新令牌的模式 + tokenGranters.add(new RefreshTokenGranter(tokenServices, clientDetailsService, requestFactory)); + // 添加隐士授权模式 + tokenGranters.add(new ImplicitTokenGranter(tokenServices, clientDetailsService, requestFactory)); + // 添加客户端模式 + tokenGranters.add(new ClientCredentialsTokenGranter(tokenServices, clientDetailsService, requestFactory)); + if (authenticationManager != null) { + // 添加密码模式 + tokenGranters.add(new ResourceOwnerPasswordTokenGranter(authenticationManager, tokenServices, clientDetailsService, requestFactory)); + } + return tokenGranters; + } + + private AuthorizationServerTokenServices tokenServices() { + if (tokenServices != null) { + return tokenServices; + } + this.tokenServices = createDefaultTokenServices(); + return tokenServices; + } + + private AuthorizationCodeServices authorizationCodeServices() { + if (authorizationCodeServices == null) { + authorizationCodeServices = new InMemoryAuthorizationCodeServices(); + } + return authorizationCodeServices; + } + + private OAuth2RequestFactory requestFactory() { + return new DefaultOAuth2RequestFactory(clientDetailsService); + } + + private DefaultTokenServices createDefaultTokenServices() { + DefaultTokenServices tokenServices = new DefaultTokenServices(); + tokenServices.setTokenStore(tokenStore); + tokenServices.setSupportRefreshToken(true); + tokenServices.setReuseRefreshToken(reuseRefreshToken); + tokenServices.setClientDetailsService(clientDetailsService); + tokenServices.setTokenEnhancer(tokenEnhancer); + addUserDetailsService(tokenServices, this.userDetailsService); + return tokenServices; + } + + private void addUserDetailsService(DefaultTokenServices tokenServices, UserDetailsService userDetailsService) { + if (userDetailsService != null) { + PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider(); + provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper<>(userDetailsService)); + tokenServices.setAuthenticationManager(new ProviderManager(Collections.singletonList(provider))); + } + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/config/ValidateCodeSecurityConfig.java b/zlt-uaa/src/main/java/com/central/oauth/config/ValidateCodeSecurityConfig.java deleted file mode 100644 index edc1ce4..0000000 --- a/zlt-uaa/src/main/java/com/central/oauth/config/ValidateCodeSecurityConfig.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * - */ -package com.central.oauth.config; - -import org.springframework.security.config.annotation.SecurityConfigurerAdapter; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.web.DefaultSecurityFilterChain; -import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; -import javax.servlet.Filter; - -/** - * 校验码相关安全配置 - * - * @author zlt - */ -@Component("validateCodeSecurityConfig") -public class ValidateCodeSecurityConfig extends SecurityConfigurerAdapter { - @Resource - private Filter validateCodeFilter; - - @Override - public void configure(HttpSecurity http) { - http.addFilterBefore(validateCodeFilter, AbstractPreAuthenticatedProcessingFilter.class); - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/controller/OAuth2Controller.java b/zlt-uaa/src/main/java/com/central/oauth/controller/OAuth2Controller.java deleted file mode 100644 index be3880a..0000000 --- a/zlt-uaa/src/main/java/com/central/oauth/controller/OAuth2Controller.java +++ /dev/null @@ -1,132 +0,0 @@ -package com.central.oauth.controller; - -import com.central.common.constant.SecurityConstants; -import com.central.common.utils.ResponseUtil; -import com.central.common.context.TenantContextHolder; -import com.central.oauth2.common.token.MobileAuthenticationToken; -import com.central.oauth2.common.token.OpenIdAuthenticationToken; -import com.central.oauth2.common.util.AuthUtils; -import com.fasterxml.jackson.databind.ObjectMapper; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections.MapUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.security.authentication.*; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException; -import org.springframework.security.oauth2.provider.*; -import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * OAuth2相关操作 - * - * @author zlt - */ -@Api(tags = "OAuth2相关操作") -@Slf4j -@RestController -public class OAuth2Controller { - @Resource - private ObjectMapper objectMapper; - - @Autowired - private PasswordEncoder passwordEncoder; - - @Resource - private AuthorizationServerTokenServices authorizationServerTokenServices; - - @Autowired - private AuthenticationManager authenticationManager; - - @Autowired - private ClientDetailsService clientDetailsService; - - @ApiOperation(value = "用户名密码获取token") - @PostMapping(SecurityConstants.PASSWORD_LOGIN_PRO_URL) - public void getUserTokenInfo( - @ApiParam(required = true, name = "username", value = "账号") String username, - @ApiParam(required = true, name = "password", value = "密码") String password, - HttpServletRequest request, HttpServletResponse response) throws IOException { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password); - writerToken(request, response, token, "用户名或密码错误"); - } - - @ApiOperation(value = "openId获取token") - @PostMapping(SecurityConstants.OPENID_TOKEN_URL) - public void getTokenByOpenId( - @ApiParam(required = true, name = "openId", value = "openId") String openId, - HttpServletRequest request, HttpServletResponse response) throws IOException { - OpenIdAuthenticationToken token = new OpenIdAuthenticationToken(openId); - writerToken(request, response, token, "openId错误"); - } - - @ApiOperation(value = "mobile获取token") - @PostMapping(SecurityConstants.MOBILE_TOKEN_URL) - public void getTokenByMobile( - @ApiParam(required = true, name = "mobile", value = "mobile") String mobile, - @ApiParam(required = true, name = "password", value = "密码") String password, - HttpServletRequest request, HttpServletResponse response) throws IOException { - MobileAuthenticationToken token = new MobileAuthenticationToken(mobile, password); - writerToken(request, response, token, "手机号或密码错误"); - } - - private void writerToken(HttpServletRequest request, HttpServletResponse response, AbstractAuthenticationToken token - , String badCredenbtialsMsg) throws IOException { - try { - final String[] clientInfos = AuthUtils.extractClient(request); - String clientId = clientInfos[0]; - String clientSecret = clientInfos[1]; - - ClientDetails clientDetails = getClient(clientId, clientSecret); - //保存租户id - TenantContextHolder.setTenant(clientId); - TokenRequest tokenRequest = new TokenRequest(MapUtils.EMPTY_MAP, clientId, clientDetails.getScope(), "customer"); - OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails); - Authentication authentication = authenticationManager.authenticate(token); - SecurityContextHolder.getContext().setAuthentication(authentication); - OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication); - OAuth2AccessToken oAuth2AccessToken = authorizationServerTokenServices.createAccessToken(oAuth2Authentication); - oAuth2Authentication.setAuthenticated(true); - TenantContextHolder.clear(); - ResponseUtil.responseSucceed(objectMapper, response, oAuth2AccessToken); - } catch (BadCredentialsException | InternalAuthenticationServiceException e) { - exceptionHandler(response, badCredenbtialsMsg); - } catch (Exception e) { - exceptionHandler(response, e); - } - } - - private void exceptionHandler(HttpServletResponse response, Exception e) throws IOException { - log.error("exceptionHandler-error:", e); - exceptionHandler(response, e.getMessage()); - } - - private void exceptionHandler(HttpServletResponse response, String msg) throws IOException { - response.setStatus(HttpStatus.UNAUTHORIZED.value()); - ResponseUtil.responseFailed(objectMapper, response, msg); - } - - private ClientDetails getClient(String clientId, String clientSecret) { - ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId); - - if (clientDetails == null) { - throw new UnapprovedClientAuthenticationException("clientId对应的信息不存在"); - } else if (!passwordEncoder.matches(clientSecret, clientDetails.getClientSecret())) { - throw new UnapprovedClientAuthenticationException("clientSecret不匹配"); - } - return clientDetails; - } -} diff --git a/zlt-uaa/src/main/java/com/central/oauth/filter/ValidateCodeFilter.java b/zlt-uaa/src/main/java/com/central/oauth/filter/ValidateCodeFilter.java deleted file mode 100644 index 80fe795..0000000 --- a/zlt-uaa/src/main/java/com/central/oauth/filter/ValidateCodeFilter.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.central.oauth.filter; - -import com.central.common.constant.SecurityConstants; -import com.central.common.utils.ResponseUtil; -import com.central.oauth.exception.ValidateCodeException; -import com.central.oauth.service.IValidateCodeService; -import com.central.oauth2.common.properties.SecurityProperties; -import com.central.oauth2.common.util.AuthUtils; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Component; -import org.springframework.util.AntPathMatcher; -import org.springframework.web.filter.OncePerRequestFilter; - -import javax.annotation.Resource; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * @author zlt - * @date 2018/11/21 - */ -@Slf4j -@Component("validateCodeFilter") -public class ValidateCodeFilter extends OncePerRequestFilter { - @Autowired - private IValidateCodeService validateCodeService; - - @Autowired - private SecurityProperties securityProperties; - - @Resource - private ObjectMapper objectMapper; - - /** - * 验证请求url与配置的url是否匹配的工具类 - */ - private AntPathMatcher pathMatcher = new AntPathMatcher(); - - /** - * 返回true代表不执行过滤器,false代表执行 - */ - @Override - protected boolean shouldNotFilter(HttpServletRequest request) { - //登录提交的时候验证验证码 - if (pathMatcher.match(SecurityConstants.PASSWORD_LOGIN_PRO_URL, request.getRequestURI())) { - //判断是否有不验证验证码的client - if (securityProperties.getCode().getIgnoreClientCode().length > 0) { - try { - final String[] clientInfos = AuthUtils.extractClient(request); - String clientId = clientInfos[0]; - for (String client : securityProperties.getCode().getIgnoreClientCode()) { - if (client.equals(clientId)) { - return true; - } - } - } catch (Exception e) { - log.error("解析client信息失败", e); - } - } - return false; - } - return true; - } - - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { - try { - validateCodeService.validate(request); - } catch (ValidateCodeException e) { - ResponseUtil.responseWriter(objectMapper, response, e.getMessage(), HttpStatus.BAD_REQUEST.value()); - return; - } - chain.doFilter(request, response); - } -} \ No newline at end of file diff --git a/zlt-uaa/src/main/java/com/central/oauth/granter/MobilePwdGranter.java b/zlt-uaa/src/main/java/com/central/oauth/granter/MobilePwdGranter.java new file mode 100644 index 0000000..f321636 --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/granter/MobilePwdGranter.java @@ -0,0 +1,54 @@ +package com.central.oauth.granter; + +import com.central.oauth2.common.token.MobileAuthenticationToken; +import com.central.oauth2.common.token.OpenIdAuthenticationToken; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; +import org.springframework.security.oauth2.provider.*; +import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; +import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * openId授权模式 + * + * @author zlt + * @date 2020/7/11 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class MobilePwdGranter extends AbstractTokenGranter { + private static final String GRANT_TYPE = "mobile_password"; + + private final AuthenticationManager authenticationManager; + + public MobilePwdGranter(AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices + , ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) { + super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); + this.authenticationManager = authenticationManager; + } + + @Override + protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) { + Map parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters()); + String mobile = parameters.get("mobile"); + String password = parameters.get("password"); + // Protect from downstream leaks of password + parameters.remove("password"); + + Authentication userAuth = new MobileAuthenticationToken(mobile, password); + ((AbstractAuthenticationToken) userAuth).setDetails(parameters); + userAuth = authenticationManager.authenticate(userAuth); + if (userAuth == null || !userAuth.isAuthenticated()) { + throw new InvalidGrantException("Could not authenticate mobile: " + mobile); + } + + OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest); + return new OAuth2Authentication(storedOAuth2Request, userAuth); + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/granter/OpenIdGranter.java b/zlt-uaa/src/main/java/com/central/oauth/granter/OpenIdGranter.java new file mode 100644 index 0000000..6178c80 --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/granter/OpenIdGranter.java @@ -0,0 +1,50 @@ +package com.central.oauth.granter; + +import com.central.oauth.service.IValidateCodeService; +import com.central.oauth2.common.token.OpenIdAuthenticationToken; +import org.springframework.security.authentication.*; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; +import org.springframework.security.oauth2.provider.*; +import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; +import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * openId授权模式 + * + * @author zlt + * @date 2020/7/11 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class OpenIdGranter extends AbstractTokenGranter { + private static final String GRANT_TYPE = "openId"; + + private final AuthenticationManager authenticationManager; + + public OpenIdGranter(AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices + , ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) { + super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); + this.authenticationManager = authenticationManager; + } + + @Override + protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) { + Map parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters()); + String openId = parameters.get("openId"); + + Authentication userAuth = new OpenIdAuthenticationToken(openId); + ((AbstractAuthenticationToken) userAuth).setDetails(parameters); + userAuth = authenticationManager.authenticate(userAuth); + if (userAuth == null || !userAuth.isAuthenticated()) { + throw new InvalidGrantException("Could not authenticate openId: " + openId); + } + + OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest); + return new OAuth2Authentication(storedOAuth2Request, userAuth); + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/granter/PwdImgCodeGranter.java b/zlt-uaa/src/main/java/com/central/oauth/granter/PwdImgCodeGranter.java new file mode 100644 index 0000000..53d2b0d --- /dev/null +++ b/zlt-uaa/src/main/java/com/central/oauth/granter/PwdImgCodeGranter.java @@ -0,0 +1,42 @@ +package com.central.oauth.granter; + +import com.central.oauth.service.IValidateCodeService; +import org.springframework.security.authentication.*; +import org.springframework.security.oauth2.provider.*; +import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter; +import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * password添加图像验证码授权模式 + * + * @author zlt + * @date 2020/7/11 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +public class PwdImgCodeGranter extends ResourceOwnerPasswordTokenGranter { + private static final String GRANT_TYPE = "password_code"; + + private final IValidateCodeService validateCodeService; + + public PwdImgCodeGranter(AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices + , ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, IValidateCodeService validateCodeService) { + super(authenticationManager, tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); + this.validateCodeService = validateCodeService; + } + + @Override + protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) { + Map parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters()); + String deviceId = parameters.get("deviceId"); + String validCode = parameters.get("validCode"); + //校验图形验证码 + validateCodeService.validate(deviceId, validCode); + + return super.getOAuth2Authentication(client, tokenRequest); + } +} diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/IValidateCodeService.java b/zlt-uaa/src/main/java/com/central/oauth/service/IValidateCodeService.java index 481fb2e..75ee0c6 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/service/IValidateCodeService.java +++ b/zlt-uaa/src/main/java/com/central/oauth/service/IValidateCodeService.java @@ -7,6 +7,9 @@ import javax.servlet.http.HttpServletRequest; /** * @author zlt * @date 2018/12/10 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 */ public interface IValidateCodeService { /** @@ -33,5 +36,5 @@ public interface IValidateCodeService { /** * 验证验证码 */ - void validate(HttpServletRequest request); + void validate(String deviceId, String validCode); } diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/ValidateCodeServiceImpl.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/ValidateCodeServiceImpl.java index 3718c08..f06072e 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/service/impl/ValidateCodeServiceImpl.java +++ b/zlt-uaa/src/main/java/com/central/oauth/service/impl/ValidateCodeServiceImpl.java @@ -12,15 +12,15 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.web.bind.ServletRequestBindingException; -import org.springframework.web.bind.ServletRequestUtils; import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; /** * @author zlt * @date 2018/12/10 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 */ @Slf4j @Service @@ -95,19 +95,12 @@ public class ValidateCodeServiceImpl implements IValidateCodeService { * 验证验证码 */ @Override - public void validate(HttpServletRequest request) { - String deviceId = request.getParameter("deviceId"); + public void validate(String deviceId, String validCode) { if (StringUtils.isBlank(deviceId)) { throw new ValidateCodeException("请在请求参数中携带deviceId参数"); } String code = this.getCode(deviceId); - String codeInRequest; - try { - codeInRequest = ServletRequestUtils.getStringParameter(request, "validCode"); - } catch (ServletRequestBindingException e) { - throw new ValidateCodeException("获取验证码的值失败"); - } - if (StringUtils.isBlank(codeInRequest)) { + if (StringUtils.isBlank(validCode)) { throw new ValidateCodeException("请填写验证码"); } @@ -115,7 +108,7 @@ public class ValidateCodeServiceImpl implements IValidateCodeService { throw new ValidateCodeException("验证码不存在或已过期"); } - if (!StringUtils.equals(code, codeInRequest.toLowerCase())) { + if (!StringUtils.equals(code, validCode.toLowerCase())) { throw new ValidateCodeException("验证码不正确"); } -- GitLab