mirror of
https://gitee.com/youlaitech/youlai-mall.git
synced 2024-12-22 20:54:26 +08:00
.
This commit is contained in:
parent
c93750d73c
commit
54747673ab
@ -1,14 +1,13 @@
|
||||
package com.youlai.mall.ums.pojo.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class MemberAuthDTO {
|
||||
|
||||
private Long id;
|
||||
private String username;
|
||||
private Long userId;
|
||||
private String openId;
|
||||
private Integer status;
|
||||
private String avatar;
|
||||
private String nickname;
|
||||
|
||||
}
|
||||
|
@ -65,13 +65,14 @@ public class MemberController {
|
||||
@ApiImplicitParam(name = "openid", value = "微信身份唯一标识", required = true, paramType = "path", dataType = "String")
|
||||
@GetMapping("/openid/{openid}")
|
||||
public Result<MemberAuthDTO> getByOpenid(@PathVariable String openid) {
|
||||
UmsMember member = iUmsMemberService.getOne(new LambdaQueryWrapper<UmsMember>().eq(UmsMember::getOpenid, openid));
|
||||
UmsMember member = iUmsMemberService.getOne(new LambdaQueryWrapper<UmsMember>().eq(UmsMember::getOpenid, openid)
|
||||
.select(UmsMember::getId,UmsMember::getOpenid,UmsMember::getStatus)
|
||||
);
|
||||
if (member == null) {
|
||||
return Result.failed(ResultCode.USER_NOT_EXIST);
|
||||
}
|
||||
// 会员认证信息
|
||||
MemberAuthDTO memberAuth = new MemberAuthDTO();
|
||||
BeanUtil.copyProperties(member, memberAuth);
|
||||
MemberAuthDTO memberAuth = new MemberAuthDTO(member.getId(),member.getOpenid(),member.getStatus());
|
||||
return Result.success(memberAuth);
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*用户业务类
|
||||
* 用户业务类
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@ -107,7 +107,8 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
|
||||
@Override
|
||||
public UserAuthDTO getByUsername(String username) {
|
||||
return this.baseMapper.getByUsername(username);
|
||||
UserAuthDTO userAuthInfo = this.baseMapper.getByUsername(username);
|
||||
return userAuthInfo;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,8 +31,19 @@
|
||||
email,gmt_create,gmt_modified,
|
||||
deleted
|
||||
</sql>
|
||||
<select id="getByUsername" resultMap="BaseResultMap">
|
||||
select t1.id, t1.username, t1.nickname, t1.password, t1.status, t3.code roleCode
|
||||
|
||||
<resultMap id="UserAuthMap" type="com.youlai.admin.pojo.dto.UserAuthDTO">
|
||||
<id property="userId" column="id" jdbcType="BIGINT"/>
|
||||
<result property="username" column="username" jdbcType="VARCHAR"/>
|
||||
<result property="password" column="password" jdbcType="VARCHAR"/>
|
||||
<result property="status" column="status" jdbcType="BOOLEAN"/>
|
||||
<collection property="roles" ofType="string" javaType="list">
|
||||
<result column="roleCode"></result>
|
||||
</collection>
|
||||
</resultMap>
|
||||
|
||||
<select id="getByUsername" resultMap="UserAuthMap">
|
||||
select t1.id userId, t1.username, t1.nickname, t1.password, t1.status, t3.code roleCode
|
||||
from sys_user t1,
|
||||
sys_user_role t2,
|
||||
sys_role t3
|
||||
|
@ -113,5 +113,4 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
@ -12,6 +12,8 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
@EnableDiscoveryClient
|
||||
public class AuthApplication {
|
||||
public static void main(String[] args) {
|
||||
|
||||
SpringApplication.run(AuthApplication.class, args);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,6 @@ import cn.hutool.json.JSONUtil;
|
||||
import com.nimbusds.jose.jwk.JWKSet;
|
||||
import com.nimbusds.jose.jwk.RSAKey;
|
||||
import com.youlai.auth.common.enums.OAuthClientEnum;
|
||||
import com.youlai.auth.domain.OAuthToken;
|
||||
import com.youlai.auth.domain.UserInfo;
|
||||
import com.youlai.auth.service.IAuthService;
|
||||
import com.youlai.common.constant.AuthConstants;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.common.web.util.JwtUtils;
|
||||
@ -37,15 +34,14 @@ import java.util.concurrent.TimeUnit;
|
||||
public class OAuthController {
|
||||
|
||||
private TokenEndpoint tokenEndpoint;
|
||||
private IAuthService wechatAuthService;
|
||||
private RedisTemplate redisTemplate;
|
||||
private KeyPair keyPair;
|
||||
|
||||
@ApiOperation(value = "OAuth2认证", notes = "login")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "grant_type", defaultValue = "password", value = "授权模式", required = true),
|
||||
@ApiImplicitParam(name = "client_id", value = "Oauth2客户端ID(新版本需放置请求头)", required = true),
|
||||
@ApiImplicitParam(name = "client_secret", value = "Oauth2客户端秘钥(新版本需放置请求头)", required = true),
|
||||
@ApiImplicitParam(name = "client_id", value = "Oauth2客户端ID", required = true),
|
||||
@ApiImplicitParam(name = "client_secret", value = "Oauth2客户端秘钥", required = true),
|
||||
@ApiImplicitParam(name = "refresh_token", value = "刷新token"),
|
||||
@ApiImplicitParam(name = "username", defaultValue = "admin", value = "登录用户名"),
|
||||
@ApiImplicitParam(name = "password", defaultValue = "123456", value = "登录密码")
|
||||
@ -74,14 +70,6 @@ public class OAuthController {
|
||||
}
|
||||
}
|
||||
|
||||
@ApiOperation(value = "微信授权登录")
|
||||
@ApiImplicitParam(name = "code", value = "小程序授权code", paramType = "path")
|
||||
@PostMapping("/wechat-token")
|
||||
public Result wechatLogin(@PathVariable String code, @RequestBody UserInfo userInfo) {
|
||||
OAuthToken token = wechatAuthService.login(code, userInfo);
|
||||
return Result.success(token);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "注销", notes = "logout")
|
||||
@DeleteMapping("/logout")
|
||||
public Result logout() {
|
||||
|
@ -1,37 +0,0 @@
|
||||
package com.youlai.auth.domain;
|
||||
|
||||
import com.youlai.auth.common.jwt.JwtPayloadBuilder;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 描述: [自定义token]
|
||||
* 创建时间: 2021/6/8
|
||||
*
|
||||
* @author hxr
|
||||
* @version 1.0.0
|
||||
* @update [序号][日期YYYY-MM-DD] [更改人姓名][变更描述]
|
||||
*/
|
||||
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@Data
|
||||
public class OAuthToken {
|
||||
|
||||
private String access_token;
|
||||
|
||||
private String token_type = "bearer";
|
||||
|
||||
public OAuthToken accessToken(String accessToken) {
|
||||
this.access_token = accessToken;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OAuthToken tokenType(String tokenType) {
|
||||
this.token_type = tokenType;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
@ -3,9 +3,9 @@ package com.youlai.auth.security.config;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.http.HttpStatus;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.youlai.auth.security.core.userdetails.system.SysUserDetails;
|
||||
import com.youlai.auth.security.core.clientdetails.ClientDetailsServiceImpl;
|
||||
import com.youlai.auth.security.core.userdetails.system.SysUserDetailsServiceImpl;
|
||||
import com.youlai.auth.security.core.userdetails.system.SysUserDetails;
|
||||
import com.youlai.auth.security.extension.wechat.WechatTokenGranter;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.common.result.ResultCode;
|
||||
import lombok.AllArgsConstructor;
|
||||
@ -16,14 +16,13 @@ import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
|
||||
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.provider.CompositeTokenGranter;
|
||||
import org.springframework.security.oauth2.provider.TokenGranter;
|
||||
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
|
||||
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
|
||||
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
|
||||
@ -42,7 +41,7 @@ import java.util.*;
|
||||
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
|
||||
|
||||
private AuthenticationManager authenticationManager;
|
||||
private SysUserDetailsServiceImpl sysUserDetailsService;
|
||||
|
||||
private ClientDetailsServiceImpl clientDetailsService;
|
||||
|
||||
/**
|
||||
@ -59,39 +58,29 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
|
||||
*/
|
||||
@Override
|
||||
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
|
||||
// Token增强
|
||||
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
|
||||
List<TokenEnhancer> tokenEnhancers = new ArrayList<>();
|
||||
tokenEnhancers.add(tokenEnhancer());
|
||||
tokenEnhancers.add(jwtAccessTokenConverter());
|
||||
tokenEnhancerChain.setTokenEnhancers(tokenEnhancers);
|
||||
|
||||
// 添加自定义授权模式
|
||||
List<TokenGranter> granterList = new ArrayList<>(Arrays.asList(endpoints.getTokenGranter()));
|
||||
granterList.add(new WechatTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory(), authenticationManager));
|
||||
CompositeTokenGranter compositeTokenGranter = new CompositeTokenGranter(granterList);
|
||||
|
||||
endpoints
|
||||
.authenticationManager(authenticationManager)
|
||||
.accessTokenConverter(jwtAccessTokenConverter())
|
||||
.tokenEnhancer(tokenEnhancerChain)
|
||||
// .userDetailsService(userDetailsService)
|
||||
.tokenGranter(compositeTokenGranter)
|
||||
// refresh token有两种使用方式:重复使用(true)、非重复使用(false),默认为true
|
||||
// 1 重复使用:access token过期刷新时, refresh token过期时间未改变,仍以初次生成的时间为准
|
||||
// 2 非重复使用:access token过期刷新时, refresh token过期时间延续,在refresh token有效期内刷新便永不失效达到无需再次登录的目的
|
||||
.reuseRefreshTokens(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 重写 DaoAuthenticationProvider
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public DaoAuthenticationProvider authenticationProvider() {
|
||||
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
||||
provider.setHideUserNotFoundExceptions(false); // 是否隐藏用户不存在异常,默认:true-隐藏;false-抛出异常;
|
||||
provider.setUserDetailsService(sysUserDetailsService);
|
||||
provider.setPasswordEncoder(passwordEncoder());
|
||||
return provider;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 使用非对称加密算法对token签名
|
||||
*/
|
||||
@ -103,7 +92,7 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
|
||||
}
|
||||
|
||||
/**
|
||||
* 从classpath下的密钥库中获取密钥对(公钥+私钥)
|
||||
* 密钥库中获取密钥对(公钥+私钥)
|
||||
*/
|
||||
@Bean
|
||||
public KeyPair keyPair() {
|
||||
@ -128,17 +117,6 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 密码编码器
|
||||
* <p>
|
||||
* 委托方式,根据密码的前缀选择对应的encoder,例如:{bcypt}前缀->标识BCYPT算法加密;{noop}->标识不使用任何加密即明文的方式
|
||||
* 密码判读 DaoAuthenticationProvider#additionalAuthenticationChecks
|
||||
*/
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义认证异常响应数据
|
||||
*/
|
||||
|
@ -1,18 +1,31 @@
|
||||
package com.youlai.auth.security.config;
|
||||
|
||||
import com.youlai.auth.security.core.userdetails.member.MemberUserDetailsServiceImpl;
|
||||
import com.youlai.auth.security.core.userdetails.system.SysUserDetailsServiceImpl;
|
||||
import com.youlai.auth.security.extension.wechat.WechatAuthenticationProvider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
private final UserDetailsService sysUserDetailsService;
|
||||
|
||||
private final UserDetailsService memberUserDetailsService;
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
@ -25,7 +38,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
}
|
||||
|
||||
/**
|
||||
* 认证管理中心
|
||||
* 认证管理对象
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
@ -35,5 +48,40 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(AuthenticationManagerBuilder auth) {
|
||||
auth.authenticationProvider(wechatAuthenticationProvider())
|
||||
.authenticationProvider(daoAuthenticationProvider());
|
||||
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WechatAuthenticationProvider wechatAuthenticationProvider() {
|
||||
WechatAuthenticationProvider provider = new WechatAuthenticationProvider();
|
||||
provider.setUserDetailsService(memberUserDetailsService);
|
||||
return provider;
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public DaoAuthenticationProvider daoAuthenticationProvider() {
|
||||
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
||||
provider.setHideUserNotFoundExceptions(false); // 是否隐藏用户不存在异常,默认:true-隐藏;false-抛出异常;
|
||||
provider.setUserDetailsService(sysUserDetailsService);
|
||||
provider.setPasswordEncoder(passwordEncoder());
|
||||
return provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* 密码编码器
|
||||
* <p>
|
||||
* 委托方式,根据密码的前缀选择对应的encoder,例如:{bcypt}前缀->标识BCYPT算法加密;{noop}->标识不使用任何加密即明文的方式
|
||||
* 密码判读 DaoAuthenticationProvider#additionalAuthenticationChecks
|
||||
*/
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import java.util.Collection;
|
||||
public class MemberUserDetails implements UserDetails {
|
||||
|
||||
private Long userId;
|
||||
private String openId;
|
||||
private Boolean enabled;
|
||||
private Collection<SimpleGrantedAuthority> authorities;
|
||||
|
||||
@ -31,11 +32,11 @@ public class MemberUserDetails implements UserDetails {
|
||||
* @param member 小程序会员用户认证信息
|
||||
*/
|
||||
public MemberUserDetails(MemberAuthDTO member) {
|
||||
this.setUserId(member.getId());
|
||||
this.setUserId(member.getUserId());
|
||||
this.setOpenId(member.getOpenId());
|
||||
this.setEnabled(GlobalConstants.STATUS_YES.equals(member.getStatus()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return this.authorities;
|
||||
@ -48,7 +49,7 @@ public class MemberUserDetails implements UserDetails {
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return null;
|
||||
return this.openId;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,10 +1,13 @@
|
||||
package com.youlai.auth.security.core.userdetails.member;
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.common.result.ResultCode;
|
||||
import com.youlai.mall.ums.api.MemberFeignClient;
|
||||
import com.youlai.mall.ums.pojo.dto.MemberAuthDTO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.authentication.AccountExpiredException;
|
||||
import org.springframework.security.authentication.DisabledException;
|
||||
@ -19,21 +22,33 @@ import org.springframework.stereotype.Service;
|
||||
*
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
*/
|
||||
@Service
|
||||
@Service("memberUserDetailsService")
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class MemberUserDetailsServiceImpl implements UserDetailsService {
|
||||
|
||||
private final MemberFeignClient memberFeignClient;
|
||||
|
||||
private final WxMaService wxMaService;
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
public UserDetails loadUserByUsername(String code) throws UsernameNotFoundException {
|
||||
MemberUserDetails userDetails = null;
|
||||
Result<MemberAuthDTO> result = memberFeignClient.loadUserByOpenId(username);
|
||||
WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
|
||||
String openid = sessionInfo.getOpenid();
|
||||
|
||||
|
||||
Result<MemberAuthDTO> result = memberFeignClient.loadUserByOpenId(openid);
|
||||
if (Result.isSuccess(result)) {
|
||||
MemberAuthDTO member = result.getData();
|
||||
if (null != member) {
|
||||
userDetails = new MemberUserDetails(member);
|
||||
} else { // 微信用户不存在同步微信用户信息注册为小程序会员
|
||||
|
||||
//wxMaService.getUserService().getUserInfo()
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
if (userDetails == null) {
|
||||
|
@ -52,18 +52,6 @@ public class SysUserDetails implements UserDetails {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 小程序会员用户体系
|
||||
*
|
||||
* @param member 小程序会员用户认证信息
|
||||
*/
|
||||
public SysUserDetails(MemberAuthDTO member) {
|
||||
this.setUserId(member.getId());
|
||||
this.setUsername(member.getUsername());
|
||||
this.setEnabled(GlobalConstants.STATUS_YES.equals(member.getStatus()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return this.authorities;
|
||||
|
@ -19,7 +19,7 @@ import org.springframework.stereotype.Service;
|
||||
*
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
*/
|
||||
@Service
|
||||
@Service("sysUserDetailsService")
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class SysUserDetailsServiceImpl implements UserDetailsService {
|
||||
|
@ -1,14 +1,9 @@
|
||||
package com.youlai.auth.domain;
|
||||
|
||||
import lombok.Data;
|
||||
package com.youlai.auth.security.extension.wechat;
|
||||
|
||||
/**
|
||||
* 描述: [微信用户信息]
|
||||
* 创建时间: 2021/6/8
|
||||
*
|
||||
* @author hxr
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
* @date 2021/9/29
|
||||
*/
|
||||
@Data
|
||||
public class UserInfo {
|
||||
|
||||
private String avatarUrl;
|
@ -1,20 +1,25 @@
|
||||
package com.youlai.auth.security.extension.wechat;
|
||||
|
||||
import com.youlai.auth.security.core.userdetails.member.MemberUserDetailsServiceImpl;
|
||||
import lombok.Data;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:xianrui0365@163.com">xianrui</a>
|
||||
* @date 2021/9/25
|
||||
*/
|
||||
@Data
|
||||
public class WechatAuthenticationProvider implements AuthenticationProvider {
|
||||
|
||||
private MemberUserDetailsServiceImpl memberUserDetailsService;
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
|
||||
/**
|
||||
* 用户认证
|
||||
*
|
||||
* @param authentication
|
||||
* @return
|
||||
* @throws AuthenticationException
|
||||
@ -22,10 +27,10 @@ public class WechatAuthenticationProvider implements AuthenticationProvider {
|
||||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
WechatAuthenticationToken authenticationToken = (WechatAuthenticationToken) authentication;
|
||||
String openId = (String) authenticationToken.getPrincipal();
|
||||
UserDetails userDetails = memberUserDetailsService.loadUserByUsername(openId);
|
||||
String code = (String) authenticationToken.getPrincipal();
|
||||
UserDetails userDetails = userDetailsService.loadUserByUsername(code);
|
||||
|
||||
WechatAuthenticationToken result = new WechatAuthenticationToken(openId, userDetails.getAuthorities());
|
||||
WechatAuthenticationToken result = new WechatAuthenticationToken(userDetails.getUsername(), userDetails.getAuthorities());
|
||||
result.setDetails(authentication.getDetails());
|
||||
return result;
|
||||
}
|
||||
|
@ -15,12 +15,23 @@ public class WechatAuthenticationToken extends AbstractAuthenticationToken {
|
||||
|
||||
private final Object principal;
|
||||
|
||||
/**
|
||||
* 账号校验之前的token构建
|
||||
*
|
||||
* @param principal
|
||||
*/
|
||||
public WechatAuthenticationToken(Object principal) {
|
||||
super(null);
|
||||
this.principal = principal;
|
||||
setAuthenticated(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 账号校验成功之后的token构建
|
||||
*
|
||||
* @param principal
|
||||
* @param authorities
|
||||
*/
|
||||
public WechatAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {
|
||||
super(authorities);
|
||||
this.principal = principal;
|
||||
@ -37,7 +48,6 @@ public class WechatAuthenticationToken extends AbstractAuthenticationToken {
|
||||
return this.principal;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
|
||||
Assert.isTrue(!isAuthenticated, "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
|
||||
|
@ -19,8 +19,8 @@ public class WechatTokenGranter extends AbstractTokenGranter {
|
||||
private static final String GRANT_TYPE = "wechat";
|
||||
private final AuthenticationManager authenticationManager;
|
||||
|
||||
protected WechatTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, String grantType, AuthenticationManager authenticationManager) {
|
||||
super(tokenServices, clientDetailsService, requestFactory, grantType);
|
||||
public WechatTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, AuthenticationManager authenticationManager) {
|
||||
super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
|
||||
this.authenticationManager = authenticationManager;
|
||||
}
|
||||
|
||||
@ -28,21 +28,27 @@ public class WechatTokenGranter extends AbstractTokenGranter {
|
||||
protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
|
||||
|
||||
Map<String, String> parameters = new LinkedHashMap(tokenRequest.getRequestParameters());
|
||||
String openId = parameters.get("openId");
|
||||
Authentication userAuth = new WechatAuthenticationToken(openId);
|
||||
String code = parameters.get("code");
|
||||
String rawData = parameters.get("rawData");
|
||||
|
||||
|
||||
|
||||
parameters.remove("code");
|
||||
parameters.remove("rawData");
|
||||
Authentication userAuth = new WechatAuthenticationToken(code); // 未认证状态
|
||||
((AbstractAuthenticationToken) userAuth).setDetails(parameters);
|
||||
|
||||
try {
|
||||
userAuth = this.authenticationManager.authenticate(userAuth); // 参数校验
|
||||
userAuth = this.authenticationManager.authenticate(userAuth); // 认证中
|
||||
} catch (Exception e) {
|
||||
throw new InvalidGrantException(e.getMessage());
|
||||
}
|
||||
|
||||
if (userAuth != null && userAuth.isAuthenticated()) {
|
||||
if (userAuth != null && userAuth.isAuthenticated()) { // 认证成功
|
||||
OAuth2Request storedOAuth2Request = this.getRequestFactory().createOAuth2Request(client, tokenRequest);
|
||||
return new OAuth2Authentication(storedOAuth2Request, userAuth);
|
||||
} else {
|
||||
throw new InvalidGrantException("Could not authenticate user: " + openId);
|
||||
} else { // 认证失败
|
||||
throw new InvalidGrantException("Could not authenticate code: " + code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +0,0 @@
|
||||
package com.youlai.auth.service;
|
||||
|
||||
import com.youlai.auth.domain.OAuthToken;
|
||||
import com.youlai.auth.domain.UserInfo;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 描述: [类型描述]
|
||||
* 创建时间: 2021/6/8
|
||||
*
|
||||
* @author hxr
|
||||
* @version 1.0.0
|
||||
* @update [序号][日期YYYY-MM-DD] [更改人姓名][变更描述]
|
||||
*/
|
||||
public interface IAuthService {
|
||||
|
||||
OAuthToken login(String code, UserInfo userInfo);
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
package com.youlai.auth.service.impl;
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import com.youlai.auth.common.jwt.JwtGenerator;
|
||||
import com.youlai.auth.domain.OAuthToken;
|
||||
import com.youlai.auth.domain.UserInfo;
|
||||
import com.youlai.auth.service.IAuthService;
|
||||
import com.youlai.common.constant.AuthConstants;
|
||||
import com.youlai.common.result.Result;
|
||||
import com.youlai.common.result.ResultCode;
|
||||
import com.youlai.mall.ums.api.MemberFeignClient;
|
||||
import com.youlai.mall.ums.pojo.entity.UmsMember;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
* @description 微信小程序认证接口
|
||||
* @createTime 2021/5/20 23:37
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class WechatAuthServiceImpl implements IAuthService {
|
||||
|
||||
private MemberFeignClient memberFeignClient;
|
||||
private WxMaService wxMaService;
|
||||
private JwtGenerator jwtGenerator;
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public OAuthToken login(String code, UserInfo userInfo) {
|
||||
// 微信小程序的授权code获取openid
|
||||
WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
|
||||
String openid = sessionInfo.getOpenid();
|
||||
Result<UmsMember> result = memberFeignClient.getByOpenid(openid);
|
||||
UmsMember member;
|
||||
if (ResultCode.USER_NOT_EXIST.getCode().equals(result.getCode())) {
|
||||
// 用户不存在,注册成为新用户
|
||||
member = new UmsMember();
|
||||
BeanUtil.copyProperties(userInfo, member);
|
||||
member.setOpenid(openid);
|
||||
Result<Long> addRes = memberFeignClient.add(member);
|
||||
Assert.isTrue(ResultCode.SUCCESS.getCode().equals(addRes.getCode()), "微信用户注册失败");
|
||||
member.setId(addRes.getData()); // 新增后有了会员ID
|
||||
} else {
|
||||
member = result.getData();
|
||||
}
|
||||
|
||||
// 自定义JWT生成
|
||||
// 1. JWT授权,一般存放用户的角色标识,用于资源服务器(网关)鉴权
|
||||
Set<String> authorities = new HashSet<>();
|
||||
// 2. JWT增强,携带用户ID等信息
|
||||
Map<String, String> additional = new HashMap<>();
|
||||
additional.put(AuthConstants.USER_ID_KEY, Convert.toStr(member.getId()));
|
||||
String accessToken = jwtGenerator.createAccessToken(authorities, additional);
|
||||
|
||||
OAuthToken token = new OAuthToken().accessToken(accessToken);
|
||||
return token;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user