mirror of
https://gitee.com/log4j/pig.git
synced 2024-12-22 12:48:58 +08:00
✨ Introducing new features. closed #I4C55T
This commit is contained in:
parent
584d72b0dc
commit
2fead0dce8
@ -16,11 +16,10 @@
|
||||
|
||||
package com.pig4cloud.pig.auth.config;
|
||||
|
||||
import com.pig4cloud.pig.auth.converter.CustomAccessTokenConverter;
|
||||
import com.pig4cloud.pig.common.security.grant.ResourceOwnerPhoneTokenGranter;
|
||||
import com.pig4cloud.pig.common.core.constant.CacheConstants;
|
||||
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
|
||||
import com.pig4cloud.pig.common.security.component.PigWebResponseExceptionTranslator;
|
||||
import com.pig4cloud.pig.common.security.grant.ResourceOwnerCustomeAppTokenGranter;
|
||||
import com.pig4cloud.pig.common.security.service.PigClientDetailsService;
|
||||
import com.pig4cloud.pig.common.security.service.PigUser;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -83,8 +82,7 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
|
||||
.tokenEnhancer(tokenEnhancer()).userDetailsService(userDetailsService)
|
||||
.authenticationManager(authenticationManager).reuseRefreshTokens(false)
|
||||
.pathMapping("/oauth/confirm_access", "/token/confirm_access")
|
||||
.exceptionTranslator(new PigWebResponseExceptionTranslator())
|
||||
.accessTokenConverter(new CustomAccessTokenConverter(pigClientDetailsService()));
|
||||
.exceptionTranslator(new PigWebResponseExceptionTranslator());
|
||||
setTokenGranter(endpoints);
|
||||
}
|
||||
|
||||
@ -92,10 +90,10 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
|
||||
// 获取默认授权类型
|
||||
TokenGranter tokenGranter = endpoints.getTokenGranter();
|
||||
ArrayList<TokenGranter> tokenGranters = new ArrayList<>(Arrays.asList(tokenGranter));
|
||||
ResourceOwnerPhoneTokenGranter resourceOwnerPhoneTokenGranter = new ResourceOwnerPhoneTokenGranter(
|
||||
ResourceOwnerCustomeAppTokenGranter resourceOwnerCustomeAppTokenGranter = new ResourceOwnerCustomeAppTokenGranter(
|
||||
authenticationManager, endpoints.getTokenServices(), endpoints.getClientDetailsService(),
|
||||
endpoints.getOAuth2RequestFactory());
|
||||
tokenGranters.add(resourceOwnerPhoneTokenGranter);
|
||||
tokenGranters.add(resourceOwnerCustomeAppTokenGranter);
|
||||
CompositeTokenGranter compositeTokenGranter = new CompositeTokenGranter(tokenGranters);
|
||||
endpoints.tokenGranter(compositeTokenGranter);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
package com.pig4cloud.pig.auth.config;
|
||||
|
||||
import com.pig4cloud.pig.common.security.grant.PhoneAuthenticationProvider;
|
||||
import com.pig4cloud.pig.common.security.grant.CustomAppAuthenticationProvider;
|
||||
import com.pig4cloud.pig.common.security.handler.FormAuthenticationFailureHandler;
|
||||
import com.pig4cloud.pig.common.security.handler.SsoLogoutSuccessHandler;
|
||||
import lombok.AllArgsConstructor;
|
||||
@ -60,8 +60,8 @@ public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
|
||||
/**
|
||||
* 不要直接使用@Bean注入 会导致默认的提供者无法注入(DaoAuthenticationProvider)
|
||||
*/
|
||||
private PhoneAuthenticationProvider phoneAuthenticationProvider() {
|
||||
PhoneAuthenticationProvider phoneAuthenticationProvider = new PhoneAuthenticationProvider();
|
||||
private CustomAppAuthenticationProvider phoneAuthenticationProvider() {
|
||||
CustomAppAuthenticationProvider phoneAuthenticationProvider = new CustomAppAuthenticationProvider();
|
||||
phoneAuthenticationProvider.setUserDetailsService(userDetailsService);
|
||||
return phoneAuthenticationProvider;
|
||||
}
|
||||
|
@ -1,37 +0,0 @@
|
||||
package com.pig4cloud.pig.auth.converter;
|
||||
|
||||
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
|
||||
import com.pig4cloud.pig.common.security.service.PigClientDetailsService;
|
||||
import com.pig4cloud.pig.common.security.service.PigUser;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.provider.ClientDetails;
|
||||
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
||||
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author hccake
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class CustomAccessTokenConverter extends DefaultAccessTokenConverter {
|
||||
|
||||
final PigClientDetailsService pigClientDetailsService;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, ?> convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
|
||||
Map<String, Object> response = (Map<String, Object>) super.convertAccessToken(token, authentication);
|
||||
|
||||
ClientDetails clientDetails = pigClientDetailsService
|
||||
.loadClientByClientId(authentication.getOAuth2Request().getClientId());
|
||||
if (clientDetails != null && clientDetails.getScope().contains("read_data_scope")) {
|
||||
PigUser principal = (PigUser) authentication.getPrincipal();
|
||||
response.put(SecurityConstants.DETAILS_USER_DATA_SCOPE, principal.getUserDataScope());
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
@ -60,7 +60,7 @@ public interface SecurityConstants {
|
||||
/**
|
||||
* 手机号登录
|
||||
*/
|
||||
String PHONE = "phone";
|
||||
String APP = "app";
|
||||
|
||||
/**
|
||||
* {bcrypt} 加密的特征码
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.pig4cloud.pig.common.security.grant;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.pig4cloud.pig.common.security.service.PigUserDetailsServiceImpl;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -11,14 +10,13 @@ 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 org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
|
||||
/**
|
||||
* @author hzq
|
||||
* @since 2021-09-14
|
||||
*/
|
||||
@Slf4j
|
||||
public class PhoneAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
|
||||
public class CustomAppAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
|
||||
|
||||
@Setter
|
||||
private UserDetailsService userDetailsService;
|
||||
@ -51,14 +49,8 @@ public class PhoneAuthenticationProvider extends AbstractUserDetailsAuthenticati
|
||||
|
||||
// 手机号
|
||||
String phone = authentication.getName();
|
||||
|
||||
if (StrUtil.equals(phone, "17034642999")) {
|
||||
throw new UsernameNotFoundException(phone);
|
||||
}
|
||||
|
||||
String code = authentication.getCredentials().toString();
|
||||
UserDetails userDetails = ((PigUserDetailsServiceImpl) userDetailsService).loadUserByPhone(phone);
|
||||
PhoneAuthenticationToken token = new PhoneAuthenticationToken(userDetails);
|
||||
CustomAppAuthenticationToken token = new CustomAppAuthenticationToken(userDetails);
|
||||
token.setDetails(authentication.getDetails());
|
||||
return token;
|
||||
}
|
||||
@ -71,7 +63,7 @@ public class PhoneAuthenticationProvider extends AbstractUserDetailsAuthenticati
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> authentication) {
|
||||
return authentication.isAssignableFrom(PhoneAuthenticationToken.class);
|
||||
return authentication.isAssignableFrom(CustomAppAuthenticationToken.class);
|
||||
}
|
||||
|
||||
}
|
@ -8,20 +8,20 @@ import org.springframework.security.core.userdetails.UserDetails;
|
||||
* @author hzq
|
||||
* @since 2021-09-14
|
||||
*/
|
||||
public class PhoneAuthenticationToken extends AbstractAuthenticationToken {
|
||||
public class CustomAppAuthenticationToken extends AbstractAuthenticationToken {
|
||||
|
||||
private final Object principal;
|
||||
|
||||
// 验证码/密码
|
||||
private String code;
|
||||
|
||||
public PhoneAuthenticationToken(String phone, String code) {
|
||||
public CustomAppAuthenticationToken(String phone, String code) {
|
||||
super(AuthorityUtils.NO_AUTHORITIES);
|
||||
this.principal = phone;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public PhoneAuthenticationToken(UserDetails sysUser) {
|
||||
public CustomAppAuthenticationToken(UserDetails sysUser) {
|
||||
super(sysUser.getAuthorities());
|
||||
this.principal = sysUser;
|
||||
super.setAuthenticated(true); // 设置认证成功 必须
|
@ -20,19 +20,19 @@ import java.util.Map;
|
||||
* @author hzq
|
||||
* @since 2021-09-14
|
||||
*/
|
||||
public class ResourceOwnerPhoneTokenGranter extends AbstractTokenGranter {
|
||||
public class ResourceOwnerCustomeAppTokenGranter extends AbstractTokenGranter {
|
||||
|
||||
private static final String GRANT_TYPE = "phone";
|
||||
private static final String GRANT_TYPE = "app";
|
||||
|
||||
private final AuthenticationManager authenticationManager;
|
||||
|
||||
public ResourceOwnerPhoneTokenGranter(AuthenticationManager authenticationManager,
|
||||
public ResourceOwnerCustomeAppTokenGranter(AuthenticationManager authenticationManager,
|
||||
AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService,
|
||||
OAuth2RequestFactory requestFactory) {
|
||||
this(authenticationManager, tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
|
||||
}
|
||||
|
||||
protected ResourceOwnerPhoneTokenGranter(AuthenticationManager authenticationManager,
|
||||
protected ResourceOwnerCustomeAppTokenGranter(AuthenticationManager authenticationManager,
|
||||
AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService,
|
||||
OAuth2RequestFactory requestFactory, String grantType) {
|
||||
super(tokenServices, clientDetailsService, requestFactory, grantType);
|
||||
@ -45,18 +45,18 @@ public class ResourceOwnerPhoneTokenGranter extends AbstractTokenGranter {
|
||||
Map<String, String> parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters());
|
||||
|
||||
// 手机号
|
||||
String phone = parameters.get("phone");
|
||||
String mobile = parameters.get("mobile");
|
||||
// 验证码/密码
|
||||
String code = parameters.get("code");
|
||||
|
||||
if (StrUtil.isBlank(phone) || StrUtil.isBlank(code)) {
|
||||
if (StrUtil.isBlank(mobile) || StrUtil.isBlank(code)) {
|
||||
throw new InvalidGrantException("Bad credentials [ params must be has phone with code ]");
|
||||
}
|
||||
|
||||
// Protect from downstream leaks of code
|
||||
parameters.remove("code");
|
||||
|
||||
Authentication userAuth = new PhoneAuthenticationToken(phone, code);
|
||||
Authentication userAuth = new CustomAppAuthenticationToken(mobile, code);
|
||||
((AbstractAuthenticationToken) userAuth).setDetails(parameters);
|
||||
try {
|
||||
userAuth = authenticationManager.authenticate(userAuth);
|
||||
@ -68,7 +68,7 @@ public class ResourceOwnerPhoneTokenGranter extends AbstractTokenGranter {
|
||||
// If the phone/code are wrong the spec says we should send 400/invalid grant
|
||||
|
||||
if (userAuth == null || !userAuth.isAuthenticated()) {
|
||||
throw new InvalidGrantException("Could not authenticate user: " + phone);
|
||||
throw new InvalidGrantException("Could not authenticate user: " + mobile);
|
||||
}
|
||||
|
||||
OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
|
@ -87,7 +87,7 @@ public class PigUserDetailsServiceImpl implements UserDetailsService {
|
||||
* @return 用户信息
|
||||
*/
|
||||
public UserDetails loadUserByPhone(String phone) {
|
||||
R<UserInfo> result = remoteUserService.infoByPhone(phone, SecurityConstants.FROM_IN);
|
||||
R<UserInfo> result = remoteUserService.infoByMobile(phone, SecurityConstants.FROM_IN);
|
||||
UserDetails userDetails = getUserDetails(result);
|
||||
return userDetails;
|
||||
}
|
||||
|
@ -70,8 +70,7 @@ public class ValidateCodeGatewayFilter extends AbstractGatewayFilterFactory<Obje
|
||||
|
||||
// 刷新token,手机号登录(也可以这里进行校验) 直接向下执行
|
||||
String grantType = request.getQueryParams().getFirst("grant_type");
|
||||
if (StrUtil.equals(SecurityConstants.REFRESH_TOKEN, grantType)
|
||||
|| StrUtil.equals(SecurityConstants.PHONE, grantType)) {
|
||||
if (StrUtil.equals(SecurityConstants.REFRESH_TOKEN, grantType)) {
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
|
||||
|
@ -53,8 +53,8 @@ public interface RemoteUserService {
|
||||
* @param from 调用标志
|
||||
* @return R
|
||||
*/
|
||||
@GetMapping("/mobile/{phone}")
|
||||
R<UserInfo> infoByPhone(@PathVariable("phone") String phone, @RequestHeader(SecurityConstants.FROM) String from);
|
||||
@GetMapping("/app/info/{mobile}")
|
||||
R<UserInfo> infoByMobile(@PathVariable("mobile") String mobile, @RequestHeader(SecurityConstants.FROM) String from);
|
||||
|
||||
/**
|
||||
* 根据部门id,查询对应的用户 id 集合
|
||||
|
@ -56,8 +56,8 @@ public class RemoteUserServiceFallbackImpl implements RemoteUserService {
|
||||
* @return R
|
||||
*/
|
||||
@Override
|
||||
public R<UserInfo> infoByPhone(String phone, String from) {
|
||||
log.error("feign 查询用户信息失败手机号码:{}", phone, cause);
|
||||
public R<UserInfo> infoByMobile(String mobile, String from) {
|
||||
log.error("feign 查询用户信息失败手机号码:{}", mobile, cause);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ package com.pig4cloud.pig.admin.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.pig4cloud.pig.admin.api.entity.SysUser;
|
||||
import com.pig4cloud.pig.admin.service.MobileService;
|
||||
import com.pig4cloud.pig.admin.service.AppService;
|
||||
import com.pig4cloud.pig.admin.service.SysUserService;
|
||||
import com.pig4cloud.pig.common.core.util.R;
|
||||
import com.pig4cloud.pig.common.security.annotation.Inner;
|
||||
@ -19,18 +19,18 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
*/
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
@RequestMapping("/mobile")
|
||||
@Api(value = "mobile", tags = "手机管理模块")
|
||||
public class MobileController {
|
||||
@RequestMapping("/app")
|
||||
@Api(value = "app", tags = "手机管理模块")
|
||||
public class AppController {
|
||||
|
||||
private final MobileService mobileService;
|
||||
private final AppService appService;
|
||||
|
||||
private final SysUserService userService;
|
||||
|
||||
@Inner(value = false)
|
||||
@GetMapping("/{mobile}")
|
||||
public R sendSmsCode(@PathVariable String mobile) {
|
||||
return mobileService.sendSmsCode(mobile);
|
||||
return appService.sendSmsCode(mobile);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -39,11 +39,11 @@ public class MobileController {
|
||||
* @return 用户信息
|
||||
*/
|
||||
@Inner
|
||||
@GetMapping("/{phone}")
|
||||
public R infoByPhone(@PathVariable String phone) {
|
||||
SysUser user = userService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getPhone, phone));
|
||||
@GetMapping("/info/{mobile}")
|
||||
public R infoByMobile(@PathVariable String mobile) {
|
||||
SysUser user = userService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getPhone, mobile));
|
||||
if (user == null) {
|
||||
return R.failed(String.format("用户信息为空 %s", phone));
|
||||
return R.failed(String.format("用户信息为空 %s", mobile));
|
||||
}
|
||||
return R.ok(userService.getUserInfo(user));
|
||||
}
|
@ -23,7 +23,7 @@ import com.pig4cloud.pig.common.core.util.R;
|
||||
* @author lengleng
|
||||
* @date 2018/11/14
|
||||
*/
|
||||
public interface MobileService {
|
||||
public interface AppService {
|
||||
|
||||
/**
|
||||
* 发送手机验证码
|
@ -19,13 +19,11 @@ package com.pig4cloud.pig.admin.service;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.pig4cloud.pig.admin.api.entity.SysUser;
|
||||
import com.pig4cloud.pig.admin.mapper.SysUserMapper;
|
||||
import com.pig4cloud.pig.common.core.constant.CacheConstants;
|
||||
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
|
||||
import com.pig4cloud.pig.common.core.constant.enums.LoginTypeEnum;
|
||||
import com.pig4cloud.pig.common.core.util.R;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -44,7 +42,7 @@ import java.util.concurrent.TimeUnit;
|
||||
@Slf4j
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class MobileServiceImpl implements MobileService {
|
||||
public class AppServiceImpl implements AppService {
|
||||
|
||||
private final RedisTemplate redisTemplate;
|
||||
|
||||
@ -65,8 +63,7 @@ public class MobileServiceImpl implements MobileService {
|
||||
return R.ok(Boolean.FALSE, "手机号未注册");
|
||||
}
|
||||
|
||||
Object codeObj = redisTemplate.opsForValue()
|
||||
.get(CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.SMS.getType() + StringPool.AT + mobile);
|
||||
Object codeObj = redisTemplate.opsForValue().get(CacheConstants.DEFAULT_CODE_KEY + mobile);
|
||||
|
||||
if (codeObj != null) {
|
||||
log.info("手机号验证码未过期:{},{}", mobile, codeObj);
|
||||
@ -75,9 +72,8 @@ public class MobileServiceImpl implements MobileService {
|
||||
|
||||
String code = RandomUtil.randomNumbers(Integer.parseInt(SecurityConstants.CODE_SIZE));
|
||||
log.debug("手机号生成验证码成功:{},{}", mobile, code);
|
||||
redisTemplate.opsForValue().set(
|
||||
CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.SMS.getType() + StringPool.AT + mobile, code,
|
||||
SecurityConstants.CODE_TIME, TimeUnit.SECONDS);
|
||||
redisTemplate.opsForValue().set(CacheConstants.DEFAULT_CODE_KEY + mobile, code, SecurityConstants.CODE_TIME,
|
||||
TimeUnit.SECONDS);
|
||||
return R.ok(Boolean.TRUE, code);
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -68,9 +69,9 @@ public class SysRoleMenuServiceImpl extends ServiceImpl<SysRoleMenuMapper, SysRo
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
// 清空userinfo
|
||||
cacheManager.getCache(CacheConstants.USER_DETAILS).clear();
|
||||
Objects.requireNonNull(cacheManager.getCache(CacheConstants.USER_DETAILS)).clear();
|
||||
// 清空全部的菜单缓存 fix #I4BM58
|
||||
cacheManager.getCache(CacheConstants.MENU_DETAILS).clear();
|
||||
Objects.requireNonNull(cacheManager.getCache(CacheConstants.MENU_DETAILS)).clear();
|
||||
return this.saveBatch(roleMenuList);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user