From 0e3e59e48f765bf9b8cde18a589dff7862dbba47 Mon Sep 17 00:00:00 2001 From: "pref_mail@163.com" Date: Tue, 7 May 2024 22:39:41 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E5=85=8D=E5=AF=86=E7=A0=81=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/granter/BladeTokenGranter.java | 2 + .../auth/granter/LocalServerTokenGranter.java | 74 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 blade-auth/src/main/java/org/springblade/auth/granter/LocalServerTokenGranter.java diff --git a/blade-auth/src/main/java/org/springblade/auth/granter/BladeTokenGranter.java b/blade-auth/src/main/java/org/springblade/auth/granter/BladeTokenGranter.java index 494999fd..cb79ad98 100644 --- a/blade-auth/src/main/java/org/springblade/auth/granter/BladeTokenGranter.java +++ b/blade-auth/src/main/java/org/springblade/auth/granter/BladeTokenGranter.java @@ -43,6 +43,8 @@ public class BladeTokenGranter { List granters = new ArrayList<>(Collections.singletonList(endpoints.getTokenGranter())); // 增加验证码模式 granters.add(new CaptchaTokenGranter(authenticationManager, endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(), bladeRedis)); + // 本地登录 + granters.add(new LocalServerTokenGranter(authenticationManager, endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(), bladeRedis)); // 增加第三方登陆模式 diff --git a/blade-auth/src/main/java/org/springblade/auth/granter/LocalServerTokenGranter.java b/blade-auth/src/main/java/org/springblade/auth/granter/LocalServerTokenGranter.java new file mode 100644 index 00000000..4e6ccb25 --- /dev/null +++ b/blade-auth/src/main/java/org/springblade/auth/granter/LocalServerTokenGranter.java @@ -0,0 +1,74 @@ +package org.springblade.auth.granter; + +import org.springblade.auth.utils.TokenUtil; +import org.springblade.common.cache.CacheNames; +import org.springblade.core.redis.cache.BladeRedis; +import org.springblade.core.tool.utils.StringUtil; +import org.springblade.core.tool.utils.WebUtil; +import org.springframework.security.authentication.*; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; +import org.springframework.security.oauth2.common.exceptions.UserDeniedAuthorizationException; +import org.springframework.security.oauth2.provider.*; +import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; +import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; + +import javax.servlet.http.HttpServletRequest; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * 本地内部服务TokenGranter + * + * @author Chill + */ +public class LocalServerTokenGranter extends AbstractTokenGranter { + + private static final String GRANT_TYPE = "localserver"; + + private final AuthenticationManager authenticationManager; + + private BladeRedis bladeRedis; + + public LocalServerTokenGranter(AuthenticationManager authenticationManager, + AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, BladeRedis bladeRedis) { + this(authenticationManager, tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); + this.bladeRedis = bladeRedis; + } + + protected LocalServerTokenGranter(AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices, + ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, String grantType) { + super(tokenServices, clientDetailsService, requestFactory, grantType); + this.authenticationManager = authenticationManager; + } + + @Override + protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) { + HttpServletRequest request = WebUtil.getRequest(); + + + Map parameters = new LinkedHashMap(tokenRequest.getRequestParameters()); + String username = parameters.get("username"); + String password = parameters.get("password"); + // Protect from downstream leaks of password + parameters.remove("password"); + + Authentication userAuth = new UsernamePasswordAuthenticationToken(username, password); + ((AbstractAuthenticationToken) userAuth).setDetails(parameters); + try { + userAuth = authenticationManager.authenticate(userAuth); + } + catch (AccountStatusException | BadCredentialsException ase) { + //covers expired, locked, disabled cases (mentioned in section 5.2, draft 31) + throw new InvalidGrantException(ase.getMessage()); + } + // If the username/password are wrong the spec says we should send 400/invalid grant + + if (userAuth == null || !userAuth.isAuthenticated()) { + throw new InvalidGrantException("Could not authenticate user: " + username); + } + + OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest); + return new OAuth2Authentication(storedOAuth2Request, userAuth); + } +} From fb3d661e0b9fd068fa79da4f9e5f90585177dacf Mon Sep 17 00:00:00 2001 From: "pref_mail@163.com" Date: Tue, 7 May 2024 23:21:30 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E5=85=8D=E5=AF=86=E7=A0=81=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/granter/BladeTokenGranter.java | 2 +- .../auth/granter/LocalServerTokenGranter.java | 108 ++++++++++++------ 2 files changed, 71 insertions(+), 39 deletions(-) diff --git a/blade-auth/src/main/java/org/springblade/auth/granter/BladeTokenGranter.java b/blade-auth/src/main/java/org/springblade/auth/granter/BladeTokenGranter.java index cb79ad98..55767619 100644 --- a/blade-auth/src/main/java/org/springblade/auth/granter/BladeTokenGranter.java +++ b/blade-auth/src/main/java/org/springblade/auth/granter/BladeTokenGranter.java @@ -44,7 +44,7 @@ public class BladeTokenGranter { // 增加验证码模式 granters.add(new CaptchaTokenGranter(authenticationManager, endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(), bladeRedis)); // 本地登录 - granters.add(new LocalServerTokenGranter(authenticationManager, endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(), bladeRedis)); + granters.add(new LocalServerTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(), userClient, socialProperties)); // 增加第三方登陆模式 diff --git a/blade-auth/src/main/java/org/springblade/auth/granter/LocalServerTokenGranter.java b/blade-auth/src/main/java/org/springblade/auth/granter/LocalServerTokenGranter.java index 4e6ccb25..4ce93cad 100644 --- a/blade-auth/src/main/java/org/springblade/auth/granter/LocalServerTokenGranter.java +++ b/blade-auth/src/main/java/org/springblade/auth/granter/LocalServerTokenGranter.java @@ -1,14 +1,44 @@ +/* + * Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com) + */ package org.springblade.auth.granter; +import me.zhyd.oauth.model.AuthCallback; +import me.zhyd.oauth.model.AuthResponse; +import me.zhyd.oauth.model.AuthUser; +import me.zhyd.oauth.request.AuthRequest; +import org.springblade.auth.constant.AuthConstant; +import org.springblade.auth.service.BladeUserDetails; import org.springblade.auth.utils.TokenUtil; -import org.springblade.common.cache.CacheNames; -import org.springblade.core.redis.cache.BladeRedis; -import org.springblade.core.tool.utils.StringUtil; +import org.springblade.core.social.props.SocialProperties; +import org.springblade.core.social.utils.SocialUtil; +import org.springblade.core.tool.api.R; +import org.springblade.core.tool.support.Kv; +import org.springblade.core.tool.utils.BeanUtil; +import org.springblade.core.tool.utils.Func; import org.springblade.core.tool.utils.WebUtil; -import org.springframework.security.authentication.*; +import org.springblade.system.entity.User; +import org.springblade.system.entity.UserInfo; +import org.springblade.system.entity.UserOauth; +import org.springblade.system.feign.IUserClient; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; -import org.springframework.security.oauth2.common.exceptions.UserDeniedAuthorizationException; import org.springframework.security.oauth2.provider.*; import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; @@ -16,59 +46,61 @@ import org.springframework.security.oauth2.provider.token.AuthorizationServerTok import javax.servlet.http.HttpServletRequest; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Objects; /** - * 本地内部服务TokenGranter + * 本地登录 * * @author Chill */ public class LocalServerTokenGranter extends AbstractTokenGranter { + private static final String GRANT_TYPE = "local_server"; + private static final Integer AUTH_SUCCESS_CODE = 2000; - private static final String GRANT_TYPE = "localserver"; - - private final AuthenticationManager authenticationManager; - - private BladeRedis bladeRedis; - - public LocalServerTokenGranter(AuthenticationManager authenticationManager, - AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, BladeRedis bladeRedis) { - this(authenticationManager, tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); - this.bladeRedis = bladeRedis; - } + private final IUserClient userClient; + private final SocialProperties socialProperties; - protected LocalServerTokenGranter(AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices, - ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, String grantType) { - super(tokenServices, clientDetailsService, requestFactory, grantType); - this.authenticationManager = authenticationManager; + protected LocalServerTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, IUserClient userClient, SocialProperties socialProperties) { + super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE); + this.userClient = userClient; + this.socialProperties = socialProperties; } @Override protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) { + // 请求头租户信息 HttpServletRequest request = WebUtil.getRequest(); + String tenantId = Func.toStr(request.getHeader(TokenUtil.TENANT_HEADER_KEY), TokenUtil.DEFAULT_TENANT_ID); + Map parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters()); - Map parameters = new LinkedHashMap(tokenRequest.getRequestParameters()); String username = parameters.get("username"); - String password = parameters.get("password"); - // Protect from downstream leaks of password - parameters.remove("password"); + tenantId = parameters.get("tenantId"); - Authentication userAuth = new UsernamePasswordAuthenticationToken(username, password); - ((AbstractAuthenticationToken) userAuth).setDetails(parameters); - try { - userAuth = authenticationManager.authenticate(userAuth); - } - catch (AccountStatusException | BadCredentialsException ase) { - //covers expired, locked, disabled cases (mentioned in section 5.2, draft 31) - throw new InvalidGrantException(ase.getMessage()); - } - // If the username/password are wrong the spec says we should send 400/invalid grant - - if (userAuth == null || !userAuth.isAuthenticated()) { - throw new InvalidGrantException("Could not authenticate user: " + username); + // 远程调用,获取认证信息 + R result = userClient.userInfo(tenantId, username); + BladeUserDetails bladeUserDetails; + if (result.isSuccess()) { + User user = result.getData().getUser(); + Kv detail = result.getData().getDetail(); + if (user == null || user.getId() == null || user.getAccount() == null) { + throw new InvalidGrantException("localserver grant failure, user is null"); + } + bladeUserDetails = new BladeUserDetails(user.getId(), + tenantId, result.getData().getOauthId(), user.getName(), user.getRealName(), user.getDeptId(), user.getPostId(), user.getRoleId(), Func.join(result.getData().getRoles()), Func.toStr(user.getAvatar(), TokenUtil.DEFAULT_AVATAR), + user.getName(), AuthConstant.ENCRYPT + user.getPassword(), detail, true, true, true, true, + AuthorityUtils.commaSeparatedStringToAuthorityList(Func.join(result.getData().getRoles()))); + } else { + throw new InvalidGrantException("localserver grant failure, feign client return error"); } + // 组装认证数据,关闭密码校验 + Authentication userAuth = new UsernamePasswordAuthenticationToken(bladeUserDetails, null, bladeUserDetails.getAuthorities()); + ((AbstractAuthenticationToken) userAuth).setDetails(parameters); OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest); + + // 返回 OAuth2Authentication return new OAuth2Authentication(storedOAuth2Request, userAuth); } + }