yshop1.8.2移除idworker,移动端springsecuriry+jwt验证改进,明细可登陆后台查看
This commit is contained in:
@ -17,7 +17,6 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
@SpringBootApplication
|
||||
@EnableTransactionManagement
|
||||
@MapperScan({"co.yixiang.modules.*.mapper"})
|
||||
@ComponentScan(basePackages = {"co.yixiang", "org.n3r.idworker"})
|
||||
public class ApiRun {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
@ -1,11 +1,15 @@
|
||||
package co.yixiang.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.format.FormatterRegistry;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.validation.MessageCodesResolver;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
|
||||
import org.springframework.web.servlet.HandlerExceptionResolver;
|
||||
@ -29,13 +33,16 @@ public class ConfigurerAdapter implements WebMvcConfigurer {
|
||||
@Value("${file.avatar}")
|
||||
private String avatar;
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
.allowCredentials(true)
|
||||
.allowedHeaders("*")
|
||||
.allowedOrigins("*")
|
||||
.allowedMethods("GET","POST","PUT","DELETE");
|
||||
@Bean
|
||||
public CorsFilter corsFilter() {
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
CorsConfiguration config = new CorsConfiguration();
|
||||
config.setAllowCredentials(true);
|
||||
config.addAllowedOrigin("*");
|
||||
config.addAllowedHeader("*");
|
||||
config.addAllowedMethod("*");
|
||||
source.registerCorsConfiguration("/**", config);
|
||||
return new CorsFilter(source);
|
||||
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.qrcode.QrCodeUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import co.yixiang.annotation.AnonymousAccess;
|
||||
import co.yixiang.aop.log.Log;
|
||||
import co.yixiang.common.api.ApiResult;
|
||||
import co.yixiang.common.web.controller.BaseController;
|
||||
@ -77,6 +78,7 @@ public class StoreBargainController extends BaseController {
|
||||
/**
|
||||
* 砍价产品列表
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@GetMapping("/bargain/list")
|
||||
@ApiOperation(value = "砍价产品列表",notes = "砍价产品列表",response = YxStoreBargainQueryVo.class)
|
||||
public ApiResult<Object> getYxStoreBargainPageList(@RequestParam(value = "page", defaultValue = "1") int page,
|
||||
|
@ -6,6 +6,7 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.qrcode.QrCodeUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import co.yixiang.annotation.AnonymousAccess;
|
||||
import co.yixiang.aop.log.Log;
|
||||
import co.yixiang.common.api.ApiResult;
|
||||
import co.yixiang.common.web.controller.BaseController;
|
||||
@ -64,6 +65,7 @@ public class StoreCombinationController extends BaseController {
|
||||
/**
|
||||
* 拼团产品列表
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@GetMapping("/combination/list")
|
||||
@ApiOperation(value = "拼团产品列表",notes = "拼团产品列表",response = YxStoreCombinationQueryVo.class)
|
||||
public ApiResult<Object> getList(@RequestParam(value = "page",defaultValue = "1") int page,
|
||||
|
@ -3,6 +3,7 @@ package co.yixiang.modules.activity.web.controller;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import co.yixiang.annotation.AnonymousAccess;
|
||||
import co.yixiang.common.api.ApiResult;
|
||||
import co.yixiang.common.web.controller.BaseController;
|
||||
import co.yixiang.modules.activity.service.YxStoreSeckillService;
|
||||
@ -50,6 +51,7 @@ public class StoreSeckillController extends BaseController {
|
||||
/**
|
||||
* 秒杀产品列表
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@GetMapping("/seckill/list/{time}")
|
||||
@ApiOperation(value = "秒杀产品列表", notes = "秒杀产品列表", response = YxStoreSeckillQueryVo.class)
|
||||
public ApiResult<Object> getYxStoreSeckillPageList(@PathVariable String time,
|
||||
@ -72,6 +74,7 @@ public class StoreSeckillController extends BaseController {
|
||||
/**
|
||||
* 根据id获取商品秒杀产品详情
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@GetMapping("/seckill/detail/{id}")
|
||||
@ApiOperation(value = "获取YxStoreSeckill对象详情", notes = "查看商品秒杀产品表", response = YxStoreSeckillQueryVo.class)
|
||||
public ApiResult<Object> getYxStoreSeckill(@PathVariable Integer id) throws Exception {
|
||||
@ -82,6 +85,7 @@ public class StoreSeckillController extends BaseController {
|
||||
/**
|
||||
* 秒杀产品时间区间
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@GetMapping("/seckill/index")
|
||||
@ApiOperation(value = "秒杀产品时间区间", notes = "秒杀产品时间区间", response = YxStoreSeckillQueryVo.class)
|
||||
public ApiResult<Object> getYxStoreSeckillIndex() throws Exception {
|
||||
|
@ -2,6 +2,7 @@ package co.yixiang.modules.manage.web.controller;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import co.yixiang.annotation.AnonymousAccess;
|
||||
import co.yixiang.common.api.ApiResult;
|
||||
import co.yixiang.common.web.controller.BaseController;
|
||||
import co.yixiang.modules.manage.service.YxExpressService;
|
||||
@ -112,6 +113,7 @@ public class ShoperController extends BaseController {
|
||||
/**
|
||||
* 快递公司
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@GetMapping("/logistics")
|
||||
@ApiOperation(value = "快递公司",notes = "快递公司")
|
||||
public ApiResult<Object> express(){
|
||||
|
@ -72,7 +72,6 @@ import com.github.binarywang.wxpay.config.WxPayConfig;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.n3r.idworker.Sid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@ -172,8 +171,6 @@ public class YxStoreOrderServiceImpl extends BaseServiceImpl<YxStoreOrderMapper,
|
||||
@Autowired
|
||||
private AlipayService alipayService;
|
||||
|
||||
@Autowired
|
||||
private Sid sid;
|
||||
|
||||
@Autowired
|
||||
private MqProducer mqProducer;
|
||||
@ -1341,7 +1338,7 @@ public class YxStoreOrderServiceImpl extends BaseServiceImpl<YxStoreOrderMapper,
|
||||
if(payPrice <= 0) payPrice = 0d;
|
||||
|
||||
//生成分布式唯一值
|
||||
String orderSn = sid.nextShort();
|
||||
String orderSn = IdUtil.getSnowflake(0,0).nextIdStr();
|
||||
//组合数据
|
||||
YxStoreOrder storeOrder = new YxStoreOrder();
|
||||
storeOrder.setUid(uid);
|
||||
@ -1410,8 +1407,8 @@ public class YxStoreOrderServiceImpl extends BaseServiceImpl<YxStoreOrderMapper,
|
||||
|
||||
|
||||
//使用MQ延时消息
|
||||
mqProducer.sendMsg("yshop-topic",storeOrder.getId().toString());
|
||||
log.info("投递延时订单id: [{}]:", storeOrder.getId());
|
||||
//mqProducer.sendMsg("yshop-topic",storeOrder.getId().toString());
|
||||
//log.info("投递延时订单id: [{}]:", storeOrder.getId());
|
||||
|
||||
return storeOrder;
|
||||
}
|
||||
|
@ -1,15 +1,14 @@
|
||||
package co.yixiang.modules.security.config;
|
||||
|
||||
import co.yixiang.modules.security.security.JwtAuthorizationTokenFilter;
|
||||
import co.yixiang.modules.security.service.JwtUserDetailsService;
|
||||
import co.yixiang.annotation.AnonymousAccess;
|
||||
import co.yixiang.modules.security.security.JwtAccessDeniedHandler;
|
||||
import co.yixiang.modules.security.security.JwtAuthenticationEntryPoint;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import co.yixiang.modules.security.security.TokenConfigurer;
|
||||
import co.yixiang.modules.security.security.TokenProvider;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
@ -19,136 +18,114 @@ import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author hupeng
|
||||
* @date 2020/01/12
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private JwtAuthenticationEntryPoint unauthorizedHandler;
|
||||
private final TokenProvider tokenProvider;
|
||||
private final CorsFilter corsFilter;
|
||||
private final JwtAuthenticationEntryPoint authenticationErrorHandler;
|
||||
private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
@Autowired
|
||||
private JwtUserDetailsService jwtUserDetailsService;
|
||||
|
||||
/**
|
||||
* 自定义基于JWT的安全过滤器
|
||||
*/
|
||||
@Autowired
|
||||
JwtAuthorizationTokenFilter authenticationTokenFilter;
|
||||
|
||||
@Value("${jwt.header}")
|
||||
private String tokenHeader;
|
||||
|
||||
@Value("${jwt.auth.path}")
|
||||
private String loginPath;
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.userDetailsService(jwtUserDetailsService)
|
||||
.passwordEncoder(passwordEncoderBean());
|
||||
public SecurityConfig(TokenProvider tokenProvider, CorsFilter corsFilter, JwtAuthenticationEntryPoint authenticationErrorHandler, JwtAccessDeniedHandler jwtAccessDeniedHandler, ApplicationContext applicationContext) {
|
||||
this.tokenProvider = tokenProvider;
|
||||
this.corsFilter = corsFilter;
|
||||
this.authenticationErrorHandler = authenticationErrorHandler;
|
||||
this.jwtAccessDeniedHandler = jwtAccessDeniedHandler;
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Bean
|
||||
GrantedAuthorityDefaults grantedAuthorityDefaults() {
|
||||
// Remove the ROLE_ prefix
|
||||
// 去除 ROLE_ 前缀
|
||||
return new GrantedAuthorityDefaults("");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoderBean() {
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
// 密码加密方式
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity httpSecurity) throws Exception {
|
||||
|
||||
// 搜寻匿名标记 url: @AnonymousAccess
|
||||
Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = applicationContext.getBean(RequestMappingHandlerMapping.class).getHandlerMethods();
|
||||
Set<String> anonymousUrls = new HashSet<>();
|
||||
for (Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethodMap.entrySet()) {
|
||||
HandlerMethod handlerMethod = infoEntry.getValue();
|
||||
AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class);
|
||||
if (null != anonymousAccess) {
|
||||
anonymousUrls.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
|
||||
}
|
||||
}
|
||||
httpSecurity
|
||||
|
||||
// 禁用 CSRF
|
||||
.csrf().disable()
|
||||
|
||||
.addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
|
||||
// 授权异常
|
||||
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
|
||||
.exceptionHandling()
|
||||
.authenticationEntryPoint(authenticationErrorHandler)
|
||||
.accessDeniedHandler(jwtAccessDeniedHandler)
|
||||
|
||||
// 防止iframe 造成跨域
|
||||
.and()
|
||||
.headers()
|
||||
.frameOptions()
|
||||
.disable()
|
||||
|
||||
// 不创建会话
|
||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
|
||||
.and()
|
||||
.sessionManagement()
|
||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||
|
||||
// 过滤请求
|
||||
.and()
|
||||
.authorizeRequests()
|
||||
// 静态资源等等
|
||||
.antMatchers(
|
||||
HttpMethod.GET,
|
||||
"/*.html",
|
||||
"/**/*.html",
|
||||
"/**/*.css",
|
||||
"/**/*.js"
|
||||
).anonymous()
|
||||
|
||||
.antMatchers( HttpMethod.POST,"/"+loginPath).anonymous()
|
||||
.antMatchers( HttpMethod.POST,"/wxapp/auth").anonymous()
|
||||
//首页
|
||||
.antMatchers("/index").anonymous()
|
||||
.antMatchers("/article/**").anonymous()
|
||||
.antMatchers("/groom/list/*").anonymous()
|
||||
.antMatchers("/search/keyword").anonymous()
|
||||
//.antMatchers("/product/hot").anonymous()
|
||||
.antMatchers("/products/**").anonymous()
|
||||
.antMatchers("/product/hot").anonymous()
|
||||
.antMatchers("/category").anonymous()
|
||||
//.antMatchers("/coupons/**").anonymous()
|
||||
.antMatchers("/image_base64").anonymous()
|
||||
.antMatchers("/register/verify").anonymous()
|
||||
.antMatchers("/register").anonymous()
|
||||
.antMatchers("/user/activity").anonymous()
|
||||
.antMatchers("/combination/list").anonymous()
|
||||
.antMatchers("/webservice/**").anonymous()
|
||||
//微信相关
|
||||
.antMatchers("/wechat/config").anonymous()
|
||||
.antMatchers("/wechat/auth").anonymous()
|
||||
.antMatchers("/share").anonymous()
|
||||
.antMatchers("/wechat/notify").anonymous()
|
||||
.antMatchers("/notify/refund").anonymous()
|
||||
.antMatchers("/wechat/serve").anonymous()
|
||||
.antMatchers("/logistics").anonymous()
|
||||
.antMatchers("/seckill/index").anonymous()
|
||||
.antMatchers("/seckill/list/**").anonymous()
|
||||
.antMatchers("/seckill/list/**").anonymous()
|
||||
.antMatchers("/seckill/detail/*").anonymous()
|
||||
.antMatchers("/bargain/list/**").anonymous()
|
||||
// 支付宝回调
|
||||
.antMatchers("/api/aliPay/return").anonymous()
|
||||
.antMatchers("/api/aliPay/notify").anonymous()
|
||||
|
||||
// swagger start
|
||||
.antMatchers("/swagger-ui.html").anonymous()
|
||||
.antMatchers("/swagger-resources/**").anonymous()
|
||||
.antMatchers("/webjars/**").anonymous()
|
||||
.antMatchers("/*/api-docs").anonymous()
|
||||
// swagger end
|
||||
|
||||
// 接口限流测试
|
||||
.antMatchers("/test/**").anonymous()
|
||||
"/**/*.js",
|
||||
"/webSocket/**"
|
||||
).permitAll()
|
||||
// swagger 文档
|
||||
.antMatchers("/swagger-ui.html").permitAll()
|
||||
.antMatchers("/swagger-resources/**").permitAll()
|
||||
.antMatchers("/webjars/**").permitAll()
|
||||
.antMatchers("/*/api-docs").permitAll()
|
||||
// 文件
|
||||
.antMatchers("/avatar/**").anonymous()
|
||||
.antMatchers("/file/**").anonymous()
|
||||
|
||||
.antMatchers("/avatar/**").permitAll()
|
||||
.antMatchers("/file/**").permitAll()
|
||||
// 阿里巴巴 druid
|
||||
.antMatchers("/druid/**").permitAll()
|
||||
// 放行OPTIONS请求
|
||||
.antMatchers(HttpMethod.OPTIONS, "/**").anonymous()
|
||||
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
|
||||
|
||||
.antMatchers("/druid/**").anonymous()
|
||||
// 自定义匿名访问所有url放行 : 允许匿名和带权限以及登录用户访问
|
||||
.antMatchers(anonymousUrls.toArray(new String[0])).permitAll()
|
||||
// 所有请求都需要认证
|
||||
.anyRequest().authenticated()
|
||||
// 防止iframe 造成跨域
|
||||
.and().headers().frameOptions().disable();
|
||||
.and().apply(securityConfigurerAdapter());
|
||||
}
|
||||
|
||||
httpSecurity
|
||||
.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
private TokenConfigurer securityConfigurerAdapter() {
|
||||
return new TokenConfigurer(tokenProvider);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
package co.yixiang.modules.security.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author hupeng
|
||||
* @date 2020/01/12
|
||||
*/
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "jwt")
|
||||
public class SecurityProperties {
|
||||
|
||||
/** Request Headers : Authorization */
|
||||
private String header;
|
||||
|
||||
/** 令牌前缀,最后留个空格 Bearer */
|
||||
private String tokenStartWith;
|
||||
|
||||
/** 必须使用最少88位的Base64对该令牌进行编码 */
|
||||
private String base64Secret;
|
||||
|
||||
/** 令牌过期时间 此处单位/毫秒 */
|
||||
private Long tokenValidityInSeconds;
|
||||
|
||||
/** 在线用户 key,根据 key 查询 redis 中在线用户的数据 */
|
||||
private String onlineKey;
|
||||
|
||||
|
||||
public String getTokenStartWith() {
|
||||
return tokenStartWith + " ";
|
||||
}
|
||||
}
|
@ -0,0 +1,469 @@
|
||||
package co.yixiang.modules.security.rest;
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
|
||||
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import co.yixiang.annotation.AnonymousAccess;
|
||||
import co.yixiang.aop.log.Log;
|
||||
import co.yixiang.common.api.ApiCode;
|
||||
import co.yixiang.common.api.ApiResult;
|
||||
import co.yixiang.exception.ErrorRequestException;
|
||||
import co.yixiang.modules.security.config.SecurityProperties;
|
||||
import co.yixiang.modules.security.rest.param.RegParam;
|
||||
import co.yixiang.modules.security.rest.param.VerityParam;
|
||||
import co.yixiang.modules.security.security.TokenProvider;
|
||||
import co.yixiang.modules.security.security.vo.AuthUser;
|
||||
import co.yixiang.modules.security.security.vo.JwtUser;
|
||||
import co.yixiang.modules.security.service.OnlineUserService;
|
||||
import co.yixiang.modules.user.entity.YxUser;
|
||||
import co.yixiang.modules.user.entity.YxWechatUser;
|
||||
import co.yixiang.modules.user.service.YxUserService;
|
||||
import co.yixiang.modules.user.service.YxWechatUserService;
|
||||
import co.yixiang.modules.user.web.vo.YxUserQueryVo;
|
||||
import co.yixiang.utils.OrderUtil;
|
||||
import co.yixiang.utils.RedisUtil;
|
||||
import co.yixiang.utils.RedisUtils;
|
||||
import co.yixiang.utils.SecurityUtils;
|
||||
import com.vdurmont.emoji.EmojiParser;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
|
||||
import me.chanjar.weixin.mp.bean.result.WxMpUser;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author hupeng
|
||||
* @date 2020/01/12
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@Api(tags = "用户授权中心")
|
||||
public class AuthController {
|
||||
|
||||
@Value("${single.login:false}")
|
||||
private Boolean singleLogin;
|
||||
private final SecurityProperties properties;
|
||||
private final RedisUtils redisUtils;
|
||||
private final UserDetailsService userDetailsService;
|
||||
private final OnlineUserService onlineUserService;
|
||||
private final TokenProvider tokenProvider;
|
||||
private final AuthenticationManagerBuilder authenticationManagerBuilder;
|
||||
private final YxUserService userService;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final WxMpService wxService;
|
||||
private final YxWechatUserService wechatUserService;
|
||||
private final WxMaService wxMaService;
|
||||
|
||||
public AuthController(SecurityProperties properties, RedisUtils redisUtils,
|
||||
UserDetailsService userDetailsService,
|
||||
OnlineUserService onlineUserService, TokenProvider tokenProvider,
|
||||
AuthenticationManagerBuilder authenticationManagerBuilder,
|
||||
YxUserService userService, PasswordEncoder passwordEncoder,
|
||||
WxMpService wxService, YxWechatUserService wechatUserService,
|
||||
WxMaService wxMaService) {
|
||||
this.properties = properties;
|
||||
this.redisUtils = redisUtils;
|
||||
this.userDetailsService = userDetailsService;
|
||||
this.onlineUserService = onlineUserService;
|
||||
this.tokenProvider = tokenProvider;
|
||||
this.authenticationManagerBuilder = authenticationManagerBuilder;
|
||||
this.userService = userService;
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
this.wxService = wxService;
|
||||
this.wechatUserService = wechatUserService;
|
||||
this.wxMaService = wxMaService;
|
||||
}
|
||||
|
||||
@Log("H5用户登录")
|
||||
@ApiOperation("H5登录授权")
|
||||
@AnonymousAccess
|
||||
@PostMapping(value = "/login")
|
||||
public ApiResult<Map<String, String>> login(@Validated @RequestBody AuthUser authUser,
|
||||
HttpServletRequest request) {
|
||||
UsernamePasswordAuthenticationToken authenticationToken =
|
||||
new UsernamePasswordAuthenticationToken(authUser.getUsername(), authUser.getPassword());
|
||||
|
||||
Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
// 生成令牌
|
||||
String token = tokenProvider.createToken(authentication);
|
||||
final JwtUser jwtUser = (JwtUser) authentication.getPrincipal();
|
||||
// 保存在线信息
|
||||
onlineUserService.save(jwtUser, token, request);
|
||||
|
||||
Date expiresTime = tokenProvider.getExpirationDateFromToken(token);
|
||||
String expiresTimeStr = DateUtil.formatDateTime(expiresTime);
|
||||
// 返回 token 与 用户信息
|
||||
Map<String, Object> authInfo = new HashMap<String, Object>(2) {{
|
||||
put("token", token);
|
||||
put("expires_time", expiresTimeStr);
|
||||
}};
|
||||
if (singleLogin) {
|
||||
//踢掉之前已经登录的token
|
||||
onlineUserService.checkLoginOnUser(authUser.getUsername(), token);
|
||||
}
|
||||
// 返回 token
|
||||
return ApiResult.ok(authInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信公众号授权
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@GetMapping("/wechat/auth")
|
||||
@ApiOperation(value = "微信公众号授权", notes = "微信公众号授权")
|
||||
public ApiResult<Object> authLogin(@RequestParam(value = "code") String code,
|
||||
@RequestParam(value = "spread") String spread,
|
||||
HttpServletRequest request) {
|
||||
|
||||
try {
|
||||
WxMpOAuth2AccessToken wxMpOAuth2AccessToken = wxService.oauth2getAccessToken(code);
|
||||
WxMpUser wxMpUser = wxService.oauth2getUserInfo(wxMpOAuth2AccessToken, null);
|
||||
String openid = wxMpUser.getOpenId();
|
||||
YxWechatUser wechatUser = wechatUserService.getUserInfo(openid);
|
||||
|
||||
|
||||
JwtUser jwtUser = null;
|
||||
if (ObjectUtil.isNotNull(wechatUser)) {
|
||||
YxUserQueryVo yxUserQueryVo = userService.getYxUserById(wechatUser.getUid());
|
||||
if (ObjectUtil.isNotNull(yxUserQueryVo)) {
|
||||
jwtUser = (JwtUser) userDetailsService.loadUserByUsername(wechatUser.getOpenid());
|
||||
} else {
|
||||
if (ObjectUtil.isNotNull(wechatUser)) {
|
||||
wechatUserService.removeById(wechatUser.getUid());
|
||||
}
|
||||
if (ObjectUtil.isNotNull(yxUserQueryVo)) {
|
||||
userService.removeById(yxUserQueryVo.getUid());
|
||||
}
|
||||
return ApiResult.fail(ApiCode.FAIL_AUTH, "授权失败");
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
//过滤掉表情
|
||||
String nickname = EmojiParser.removeAllEmojis(wxMpUser.getNickname());
|
||||
log.info("昵称:{}", nickname);
|
||||
//用户保存
|
||||
YxUser user = new YxUser();
|
||||
user.setAccount(nickname);
|
||||
user.setUsername(wxMpUser.getOpenId());
|
||||
user.setPassword(passwordEncoder.encode("123456"));
|
||||
user.setPwd(passwordEncoder.encode("123456"));
|
||||
user.setPhone("");
|
||||
user.setUserType("wechat");
|
||||
user.setAddTime(OrderUtil.getSecondTimestampTwo());
|
||||
user.setLastTime(OrderUtil.getSecondTimestampTwo());
|
||||
user.setNickname(nickname);
|
||||
user.setAvatar(wxMpUser.getHeadImgUrl());
|
||||
user.setNowMoney(BigDecimal.ZERO);
|
||||
user.setBrokeragePrice(BigDecimal.ZERO);
|
||||
user.setIntegral(BigDecimal.ZERO);
|
||||
|
||||
userService.save(user);
|
||||
|
||||
|
||||
//保存微信用户
|
||||
YxWechatUser yxWechatUser = new YxWechatUser();
|
||||
yxWechatUser.setAddTime(OrderUtil.getSecondTimestampTwo());
|
||||
yxWechatUser.setNickname(nickname);
|
||||
yxWechatUser.setOpenid(wxMpUser.getOpenId());
|
||||
int sub = 0;
|
||||
if (ObjectUtil.isNotNull(wxMpUser.getSubscribe()) && wxMpUser.getSubscribe()) sub = 1;
|
||||
yxWechatUser.setSubscribe(sub);
|
||||
yxWechatUser.setSex(wxMpUser.getSex());
|
||||
yxWechatUser.setLanguage(wxMpUser.getLanguage());
|
||||
yxWechatUser.setCity(wxMpUser.getCity());
|
||||
yxWechatUser.setProvince(wxMpUser.getProvince());
|
||||
yxWechatUser.setCountry(wxMpUser.getCountry());
|
||||
yxWechatUser.setHeadimgurl(wxMpUser.getHeadImgUrl());
|
||||
if (ObjectUtil.isNotNull(wxMpUser.getSubscribeTime())) {
|
||||
yxWechatUser.setSubscribeTime(wxMpUser.getSubscribeTime().intValue());
|
||||
}
|
||||
if (StrUtil.isNotEmpty(wxMpUser.getUnionId())) {
|
||||
yxWechatUser.setUnionid(wxMpUser.getUnionId());
|
||||
}
|
||||
if (StrUtil.isNotEmpty(wxMpUser.getRemark())) {
|
||||
yxWechatUser.setUnionid(wxMpUser.getRemark());
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(wxMpUser.getGroupId())) {
|
||||
yxWechatUser.setGroupid(wxMpUser.getGroupId());
|
||||
}
|
||||
yxWechatUser.setUid(user.getUid());
|
||||
|
||||
wechatUserService.save(yxWechatUser);
|
||||
|
||||
|
||||
jwtUser = (JwtUser) userDetailsService.loadUserByUsername(wxMpUser.getOpenId());
|
||||
}
|
||||
|
||||
|
||||
//设置推广关系
|
||||
if (StrUtil.isNotEmpty(spread) && !spread.equals("NaN")) {
|
||||
//System.out.println("spread:"+spread);
|
||||
userService.setSpread(Integer.valueOf(spread),
|
||||
jwtUser.getId().intValue());
|
||||
}
|
||||
|
||||
UsernamePasswordAuthenticationToken authenticationToken =
|
||||
new UsernamePasswordAuthenticationToken(jwtUser.getUsername(),
|
||||
"123456");
|
||||
|
||||
Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
// 生成令牌
|
||||
String token = tokenProvider.createToken(authentication);
|
||||
final JwtUser jwtUserT = (JwtUser) authentication.getPrincipal();
|
||||
// 保存在线信息
|
||||
onlineUserService.save(jwtUserT, token, request);
|
||||
|
||||
Date expiresTime = tokenProvider.getExpirationDateFromToken(token);
|
||||
String expiresTimeStr = DateUtil.formatDateTime(expiresTime);
|
||||
|
||||
Map<String, String> map = new LinkedHashMap<>();
|
||||
map.put("token", token);
|
||||
map.put("expires_time", expiresTimeStr);
|
||||
|
||||
// 返回 token
|
||||
return ApiResult.ok(map);
|
||||
} catch (WxErrorException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
return ApiResult.fail("授权失败");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 小程序登陆接口
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@PostMapping("/wxapp/auth")
|
||||
@ApiOperation(value = "小程序登陆", notes = "小程序登陆")
|
||||
public ApiResult<Object> login(@RequestParam(value = "code") String code,
|
||||
@RequestParam(value = "spread") String spread,
|
||||
@RequestParam(value = "encryptedData") String encryptedData,
|
||||
@RequestParam(value = "iv") String iv,
|
||||
HttpServletRequest request) {
|
||||
if (StringUtils.isBlank(code)) {
|
||||
return ApiResult.fail("请传code");
|
||||
}
|
||||
try {
|
||||
//读取redis配置
|
||||
String appId = RedisUtil.get("wxapp_appId");
|
||||
String secret = RedisUtil.get("wxapp_secret");
|
||||
if (StrUtil.isBlank(appId) || StrUtil.isBlank(secret)) {
|
||||
throw new ErrorRequestException("请先配置小程序");
|
||||
}
|
||||
WxMaDefaultConfigImpl wxMaConfig = new WxMaDefaultConfigImpl();
|
||||
wxMaConfig.setAppid(appId);
|
||||
wxMaConfig.setSecret(secret);
|
||||
|
||||
|
||||
wxMaService.setWxMaConfig(wxMaConfig);
|
||||
WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(code);
|
||||
YxWechatUser wechatUser = wechatUserService.getUserInfo(session.getOpenid());
|
||||
;
|
||||
JwtUser jwtUser = null;
|
||||
if (ObjectUtil.isNotNull(wechatUser)) {
|
||||
YxUserQueryVo yxUserQueryVo = userService.getYxUserById(wechatUser.getUid());
|
||||
if (ObjectUtil.isNotNull(yxUserQueryVo)) {
|
||||
jwtUser = (JwtUser) userDetailsService.loadUserByUsername(wechatUser.getOpenid());
|
||||
} else {
|
||||
if (ObjectUtil.isNotNull(wechatUser)) {
|
||||
wechatUserService.removeById(wechatUser.getUid());
|
||||
}
|
||||
if (ObjectUtil.isNotNull(yxUserQueryVo)) {
|
||||
userService.removeById(yxUserQueryVo.getUid());
|
||||
}
|
||||
return ApiResult.fail(ApiCode.FAIL_AUTH, "授权失败");
|
||||
}
|
||||
|
||||
} else {
|
||||
WxMaUserInfo wxMpUser = wxMaService.getUserService()
|
||||
.getUserInfo(session.getSessionKey(), encryptedData, iv);
|
||||
//过滤掉表情
|
||||
String nickname = EmojiParser.removeAllEmojis(wxMpUser.getNickName());
|
||||
//用户保存
|
||||
YxUser user = new YxUser();
|
||||
user.setAccount(nickname);
|
||||
user.setUsername(wxMpUser.getOpenId());
|
||||
user.setPassword(passwordEncoder.encode("123456"));
|
||||
user.setPwd(passwordEncoder.encode("123456"));
|
||||
user.setPhone("");
|
||||
user.setUserType("routine");
|
||||
user.setAddTime(OrderUtil.getSecondTimestampTwo());
|
||||
user.setLastTime(OrderUtil.getSecondTimestampTwo());
|
||||
user.setNickname(nickname);
|
||||
user.setAvatar(wxMpUser.getAvatarUrl());
|
||||
user.setNowMoney(BigDecimal.ZERO);
|
||||
user.setBrokeragePrice(BigDecimal.ZERO);
|
||||
user.setIntegral(BigDecimal.ZERO);
|
||||
|
||||
userService.save(user);
|
||||
|
||||
|
||||
//保存微信用户
|
||||
YxWechatUser yxWechatUser = new YxWechatUser();
|
||||
// System.out.println("wxMpUser:"+wxMpUser);
|
||||
yxWechatUser.setAddTime(OrderUtil.getSecondTimestampTwo());
|
||||
yxWechatUser.setNickname(nickname);
|
||||
yxWechatUser.setRoutineOpenid(wxMpUser.getOpenId());
|
||||
int sub = 0;
|
||||
yxWechatUser.setSubscribe(sub);
|
||||
yxWechatUser.setSex(Integer.valueOf(wxMpUser.getGender()));
|
||||
yxWechatUser.setLanguage(wxMpUser.getLanguage());
|
||||
yxWechatUser.setCity(wxMpUser.getCity());
|
||||
yxWechatUser.setProvince(wxMpUser.getProvince());
|
||||
yxWechatUser.setCountry(wxMpUser.getCountry());
|
||||
yxWechatUser.setHeadimgurl(wxMpUser.getAvatarUrl());
|
||||
if (StrUtil.isNotEmpty(wxMpUser.getUnionId())) {
|
||||
yxWechatUser.setUnionid(wxMpUser.getUnionId());
|
||||
}
|
||||
yxWechatUser.setUid(user.getUid());
|
||||
|
||||
wechatUserService.save(yxWechatUser);
|
||||
|
||||
|
||||
jwtUser = (JwtUser) userDetailsService.loadUserByUsername(wxMpUser.getOpenId());
|
||||
}
|
||||
|
||||
|
||||
//设置推广关系
|
||||
if (StrUtil.isNotEmpty(spread)) {
|
||||
userService.setSpread(Integer.valueOf(spread),
|
||||
jwtUser.getId().intValue());
|
||||
}
|
||||
|
||||
UsernamePasswordAuthenticationToken authenticationToken =
|
||||
new UsernamePasswordAuthenticationToken(jwtUser.getUsername(),
|
||||
"123456");
|
||||
|
||||
Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
// 生成令牌
|
||||
String token = tokenProvider.createToken(authentication);
|
||||
final JwtUser jwtUserT = (JwtUser) authentication.getPrincipal();
|
||||
// 保存在线信息
|
||||
onlineUserService.save(jwtUserT, token, request);
|
||||
|
||||
Date expiresTime = tokenProvider.getExpirationDateFromToken(token);
|
||||
String expiresTimeStr = DateUtil.formatDateTime(expiresTime);
|
||||
|
||||
|
||||
Map<String, String> map = new LinkedHashMap<>();
|
||||
map.put("token", token);
|
||||
map.put("expires_time", expiresTimeStr);
|
||||
|
||||
// 返回 token
|
||||
return ApiResult.ok(map);
|
||||
} catch (WxErrorException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return ApiResult.fail(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@AnonymousAccess
|
||||
@PostMapping("/register/verify")
|
||||
@ApiOperation(value = "验证码发送", notes = "验证码发送")
|
||||
public ApiResult<String> verify(@Validated @RequestBody VerityParam param) {
|
||||
Boolean isTest = true;
|
||||
YxUser yxUser = userService.findByName(param.getPhone());
|
||||
if (param.getType().equals("register") && ObjectUtil.isNotNull(yxUser)) {
|
||||
return ApiResult.fail("手机号已注册");
|
||||
}
|
||||
if (param.getType().equals("login") && ObjectUtil.isNull(yxUser)) {
|
||||
return ApiResult.fail("账号不存在");
|
||||
}
|
||||
if (ObjectUtil.isNotNull(redisUtils.get("code_" + param.getPhone()))) {
|
||||
return ApiResult.fail("10分钟内有效:" + redisUtils.get("code_" + param.getPhone()).toString());
|
||||
}
|
||||
String code = RandomUtil.randomNumbers(6);
|
||||
redisUtils.set("code_" + param.getPhone(), code, 600L);
|
||||
if (isTest) {
|
||||
return ApiResult.fail("测试阶段验证码:" + code);
|
||||
}
|
||||
return ApiResult.ok("发送成功");
|
||||
}
|
||||
|
||||
@AnonymousAccess
|
||||
@PostMapping("/register")
|
||||
@ApiOperation(value = "H5注册新用户", notes = "H5注册新用户")
|
||||
public ApiResult<String> register(@Validated @RequestBody RegParam param) {
|
||||
String code = redisUtils.get("code_" + param.getAccount()).toString();
|
||||
if (StrUtil.isEmpty(code)) {
|
||||
return ApiResult.fail("请先获取验证码");
|
||||
}
|
||||
|
||||
if (!StrUtil.equals(code, param.getCaptcha())) {
|
||||
return ApiResult.fail("验证码错误");
|
||||
}
|
||||
|
||||
YxUser yxUser = userService.findByName(param.getAccount());
|
||||
if (ObjectUtil.isNotNull(yxUser)) {
|
||||
return ApiResult.fail("用户已存在");
|
||||
}
|
||||
|
||||
YxUser user = new YxUser();
|
||||
user.setAccount(param.getAccount());
|
||||
user.setUsername(param.getAccount());
|
||||
user.setPassword(passwordEncoder.encode(param.getPassword()));
|
||||
user.setPwd(passwordEncoder.encode(param.getPassword()));
|
||||
user.setPhone(param.getAccount());
|
||||
user.setUserType("h5");
|
||||
user.setAddTime(OrderUtil.getSecondTimestampTwo());
|
||||
user.setLastTime(OrderUtil.getSecondTimestampTwo());
|
||||
user.setNickname(param.getAccount());
|
||||
user.setAvatar("https://image.dayouqiantu.cn/5dc2c7f3a104c.png");
|
||||
user.setNowMoney(BigDecimal.ZERO);
|
||||
user.setBrokeragePrice(BigDecimal.ZERO);
|
||||
user.setIntegral(BigDecimal.ZERO);
|
||||
|
||||
userService.save(user);
|
||||
|
||||
return ApiResult.ok("注册成功");
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation("获取用户信息")
|
||||
@GetMapping(value = "/info")
|
||||
public ApiResult<Object> getUserInfo() {
|
||||
JwtUser jwtUser = (JwtUser) userDetailsService.loadUserByUsername(SecurityUtils.getUsername());
|
||||
return ApiResult.ok(jwtUser);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(value = "退出登录", notes = "退出登录")
|
||||
@AnonymousAccess
|
||||
@PostMapping(value = "/auth/logout")
|
||||
public ApiResult<Object> logout(HttpServletRequest request) {
|
||||
onlineUserService.logout(tokenProvider.getToken(request));
|
||||
return ApiResult.ok("退出成功");
|
||||
}
|
||||
}
|
@ -1,183 +0,0 @@
|
||||
package co.yixiang.modules.security.rest;
|
||||
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import co.yixiang.aop.log.Log;
|
||||
import co.yixiang.common.api.ApiResult;
|
||||
import co.yixiang.common.web.controller.BaseController;
|
||||
import co.yixiang.modules.monitor.service.RedisService;
|
||||
import co.yixiang.modules.security.rest.param.RegParam;
|
||||
import co.yixiang.modules.security.rest.param.VerityParam;
|
||||
import co.yixiang.modules.security.security.AuthorizationUser;
|
||||
import co.yixiang.modules.security.security.JwtUser;
|
||||
import co.yixiang.modules.security.utils.JwtTokenUtil;
|
||||
import co.yixiang.modules.user.entity.YxUser;
|
||||
import co.yixiang.modules.user.service.YxUserService;
|
||||
import co.yixiang.utils.EncryptUtils;
|
||||
import co.yixiang.utils.OrderUtil;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.authentication.AccountExpiredException;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* @author hupeng
|
||||
* @date 2019-10-01
|
||||
* 授权、根据token获取用户详细信息
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@Api(value = "H5认证模块", tags = "H5认证模块", description = "H5认证模块")
|
||||
public class AuthenticationController extends BaseController {
|
||||
|
||||
@Value("${jwt.header}")
|
||||
private String tokenHeader;
|
||||
|
||||
@Autowired
|
||||
private JwtTokenUtil jwtTokenUtil;
|
||||
|
||||
|
||||
@Autowired
|
||||
@Qualifier("jwtUserDetailsService")
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
|
||||
@Autowired
|
||||
private YxUserService userService;
|
||||
|
||||
/**
|
||||
* 登录授权
|
||||
* @param authorizationUser
|
||||
* @return
|
||||
*/
|
||||
@Log("用户登录")
|
||||
@PostMapping(value = "${jwt.auth.path}")
|
||||
@ApiOperation(value = "用户登录",notes = "用户登录")
|
||||
public ApiResult<Map<String,String>> login(@Validated @RequestBody AuthorizationUser authorizationUser){
|
||||
|
||||
final JwtUser jwtUser = (JwtUser) userDetailsService.loadUserByUsername(authorizationUser.getAccount());
|
||||
|
||||
if(!jwtUser.getPassword().equals(EncryptUtils.encryptPassword(authorizationUser.getPassword()))){
|
||||
throw new AccountExpiredException("密码错误");
|
||||
}
|
||||
|
||||
if(!jwtUser.isEnabled()){
|
||||
throw new AccountExpiredException("账号已停用,请联系管理员");
|
||||
}
|
||||
|
||||
|
||||
//设置推广关系
|
||||
if(StrUtil.isNotEmpty(authorizationUser.getSpread()) &&
|
||||
!authorizationUser.getSpread().equals("NaN")){
|
||||
userService.setSpread(Integer.valueOf(authorizationUser.getSpread()),
|
||||
jwtUser.getId().intValue());
|
||||
}
|
||||
|
||||
|
||||
// 生成令牌
|
||||
final String token = jwtTokenUtil.generateToken(jwtUser);
|
||||
|
||||
Date expiresTime = jwtTokenUtil.getExpirationDateFromToken(token);
|
||||
|
||||
String expiresTimeStr = DateUtil.formatDateTime(expiresTime);
|
||||
|
||||
Map<String,String> map = new LinkedHashMap<>();
|
||||
|
||||
map.put("token",token);
|
||||
map.put("expires_time",expiresTimeStr);
|
||||
|
||||
// 返回 token
|
||||
return ApiResult.ok(map);
|
||||
}
|
||||
|
||||
@PostMapping("/register/verify")
|
||||
@ApiOperation(value = "验证码发送",notes = "验证码发送")
|
||||
public ApiResult<String> verify(@Validated @RequestBody VerityParam param){
|
||||
Boolean isTest = true;
|
||||
YxUser yxUser = userService.findByName(param.getPhone());
|
||||
if(param.getType().equals("register") && ObjectUtil.isNotNull(yxUser)){
|
||||
return ApiResult.fail("手机号已注册");
|
||||
}
|
||||
if(param.getType().equals("login") && ObjectUtil.isNull(yxUser)){
|
||||
return ApiResult.fail("账号不存在");
|
||||
}
|
||||
if(StrUtil.isNotEmpty(redisService.getCodeVal("code_"+param.getPhone()))){
|
||||
return ApiResult.fail("10分钟内有效:"+redisService.getCodeVal("code_"+param.getPhone()));
|
||||
}
|
||||
String code = RandomUtil.randomNumbers(6);
|
||||
redisService.saveCode("code_"+param.getPhone(),code,600L);
|
||||
if(isTest){
|
||||
return ApiResult.fail("测试阶段验证码:"+code);
|
||||
}
|
||||
return ApiResult.ok("发送成功");
|
||||
}
|
||||
|
||||
@PostMapping("/register")
|
||||
@ApiOperation(value = "H5注册新用户",notes = "H5注册新用户")
|
||||
public ApiResult<String> register(@Validated @RequestBody RegParam param){
|
||||
String code = redisService.getCodeVal("code_"+param.getAccount());
|
||||
if(StrUtil.isEmpty(code)){
|
||||
return ApiResult.fail("请先获取验证码");
|
||||
}
|
||||
|
||||
if(!StrUtil.equals(code,param.getCaptcha())){
|
||||
return ApiResult.fail("验证码错误");
|
||||
}
|
||||
|
||||
YxUser yxUser = userService.findByName(param.getAccount());
|
||||
if(ObjectUtil.isNotNull(yxUser)){
|
||||
return ApiResult.fail("用户已存在");
|
||||
}
|
||||
|
||||
YxUser user = new YxUser();
|
||||
user.setAccount(param.getAccount());
|
||||
user.setUsername(param.getAccount());
|
||||
user.setPassword(EncryptUtils.encryptPassword(param.getPassword()));
|
||||
user.setPwd(EncryptUtils.encryptPassword(param.getPassword()));
|
||||
user.setPhone(param.getAccount());
|
||||
user.setUserType("h5");
|
||||
user.setAddTime(OrderUtil.getSecondTimestampTwo());
|
||||
user.setLastTime(OrderUtil.getSecondTimestampTwo());
|
||||
user.setNickname(param.getAccount());
|
||||
user.setAvatar("https://image.dayouqiantu.cn/5dc2c7f3a104c.png");
|
||||
user.setNowMoney(BigDecimal.ZERO);
|
||||
user.setBrokeragePrice(BigDecimal.ZERO);
|
||||
user.setIntegral(BigDecimal.ZERO);
|
||||
|
||||
userService.save(user);
|
||||
|
||||
return ApiResult.ok("注册成功");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(value = "/auth/logout")
|
||||
@ApiOperation(value = "退出登录",notes = "退出登录")
|
||||
public ApiResult logout(){
|
||||
return ApiResult.ok("退出成功");
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
package co.yixiang.modules.security.security;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @date 2018-11-23
|
||||
* 返回token
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class AuthenticationInfo implements Serializable {
|
||||
|
||||
private final String token;
|
||||
|
||||
private final JwtUser user;
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package co.yixiang.modules.security.security;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @date 2019-6-5 17:29:57
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class ImgResult {
|
||||
|
||||
private String img;
|
||||
|
||||
private String uuid;
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package co.yixiang.modules.security.security;
|
||||
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author hupeng
|
||||
* @date 2020/01/12
|
||||
*/
|
||||
@Component
|
||||
public class JwtAccessDeniedHandler implements AccessDeniedHandler {
|
||||
|
||||
@Override
|
||||
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
|
||||
//将调用此方法发送403 Forbidden响应
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage());
|
||||
}
|
||||
}
|
@ -7,20 +7,19 @@ import org.springframework.stereotype.Component;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author hupeng
|
||||
* @date 2020/01/12
|
||||
*/
|
||||
@Component
|
||||
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {
|
||||
|
||||
private static final long serialVersionUID = -8970718410437077606L;
|
||||
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||
|
||||
@Override
|
||||
public void commence(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
AuthenticationException authException) throws IOException {
|
||||
/**
|
||||
* 当用户尝试访问安全的REST资源而不提供任何凭据时,将调用此方法发送401 响应
|
||||
*/
|
||||
//将调用此方法发送401 响应
|
||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException==null?"Unauthorized":authException.getMessage());
|
||||
}
|
||||
}
|
||||
|
@ -1,67 +0,0 @@
|
||||
package co.yixiang.modules.security.security;
|
||||
|
||||
import io.jsonwebtoken.ExpiredJwtException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import co.yixiang.modules.security.utils.JwtTokenUtil;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class JwtAuthorizationTokenFilter extends OncePerRequestFilter {
|
||||
|
||||
private final UserDetailsService userDetailsService;
|
||||
private final JwtTokenUtil jwtTokenUtil;
|
||||
private final String tokenHeader;
|
||||
|
||||
public JwtAuthorizationTokenFilter(@Qualifier("jwtUserDetailsService") UserDetailsService userDetailsService, JwtTokenUtil jwtTokenUtil, @Value("${jwt.header}") String tokenHeader) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
this.jwtTokenUtil = jwtTokenUtil;
|
||||
this.tokenHeader = tokenHeader;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
|
||||
|
||||
final String requestHeader = request.getHeader(this.tokenHeader);
|
||||
|
||||
String username = null;
|
||||
String authToken = null;
|
||||
if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
|
||||
authToken = requestHeader.substring(7);
|
||||
try {
|
||||
username = jwtTokenUtil.getUsernameFromToken(authToken);
|
||||
} catch (ExpiredJwtException e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
|
||||
// It is not compelling necessary to load the use details from the database. You could also store the information
|
||||
// in the token and read it from it. It's up to you ;)
|
||||
JwtUser userDetails = (JwtUser)this.userDetailsService.loadUserByUsername(username);
|
||||
|
||||
// For simple validation it is completely sufficient to just check the token integrity. You don't have to call
|
||||
// the database compellingly. Again it's up to you ;)
|
||||
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
|
||||
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
}
|
||||
}
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package co.yixiang.modules.security.security;
|
||||
|
||||
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.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
/**
|
||||
* @author hupeng
|
||||
* @date 2020/01/12
|
||||
*/
|
||||
public class TokenConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
|
||||
|
||||
private final TokenProvider tokenProvider;
|
||||
|
||||
public TokenConfigurer(TokenProvider tokenProvider){
|
||||
this.tokenProvider = tokenProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(HttpSecurity http) {
|
||||
TokenFilter customFilter = new TokenFilter(tokenProvider);
|
||||
http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
package co.yixiang.modules.security.security;
|
||||
|
||||
import co.yixiang.modules.security.config.SecurityProperties;
|
||||
import co.yixiang.modules.security.security.vo.JwtUser;
|
||||
import co.yixiang.modules.security.security.vo.OnlineUser;
|
||||
import co.yixiang.modules.security.service.OnlineUserService;
|
||||
import co.yixiang.utils.SpringContextHolder;
|
||||
import io.jsonwebtoken.ExpiredJwtException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.filter.GenericFilterBean;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author hupeng
|
||||
* @date 2020/01/12
|
||||
*/
|
||||
@Slf4j
|
||||
public class TokenFilter extends GenericFilterBean {
|
||||
|
||||
private final TokenProvider tokenProvider;
|
||||
|
||||
TokenFilter(TokenProvider tokenProvider) {
|
||||
this.tokenProvider = tokenProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
|
||||
throws IOException, ServletException {
|
||||
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
|
||||
String token = resolveToken(httpServletRequest);
|
||||
String requestRri = httpServletRequest.getRequestURI();
|
||||
// 验证 token 是否存在
|
||||
OnlineUser onlineUser = null;
|
||||
try {
|
||||
SecurityProperties properties = SpringContextHolder.getBean(SecurityProperties.class);
|
||||
OnlineUserService onlineUserService = SpringContextHolder.getBean(OnlineUserService.class);
|
||||
onlineUser = onlineUserService.getOne(properties.getOnlineKey() + token);
|
||||
} catch (ExpiredJwtException e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
if (onlineUser != null && StringUtils.hasText(token) && tokenProvider.validateToken(token)) {
|
||||
//Authentication authentication = tokenProvider.getAuthentication(token);
|
||||
//SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
JwtUser userDetails = new JwtUser(onlineUser.getId(),
|
||||
onlineUser.getUserName(),onlineUser.getNickName(),"","","",
|
||||
new ArrayList<>(),true,0);
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||
userDetails, null,
|
||||
new ArrayList<>());
|
||||
//authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
|
||||
log.debug("set Authentication to security context for '{}', uri: {}", authentication.getName(), requestRri);
|
||||
} else {
|
||||
log.debug("no valid JWT token found, uri: {}", requestRri);
|
||||
}
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
}
|
||||
|
||||
private String resolveToken(HttpServletRequest request) {
|
||||
SecurityProperties properties = SpringContextHolder.getBean(SecurityProperties.class);
|
||||
String bearerToken = request.getHeader(properties.getHeader());
|
||||
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(properties.getTokenStartWith())) {
|
||||
return bearerToken.substring(7);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,116 @@
|
||||
package co.yixiang.modules.security.security;
|
||||
|
||||
import co.yixiang.modules.security.config.SecurityProperties;
|
||||
import io.jsonwebtoken.*;
|
||||
import io.jsonwebtoken.io.Decoders;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.security.Key;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author hupeng
|
||||
* @date 2020/01/12
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class TokenProvider implements InitializingBean {
|
||||
|
||||
private final SecurityProperties properties;
|
||||
private static final String AUTHORITIES_KEY = "auth";
|
||||
private Key key;
|
||||
|
||||
public TokenProvider(SecurityProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
byte[] keyBytes = Decoders.BASE64.decode(properties.getBase64Secret());
|
||||
this.key = Keys.hmacShaKeyFor(keyBytes);
|
||||
}
|
||||
|
||||
public String createToken(Authentication authentication) {
|
||||
String authorities = authentication.getAuthorities().stream()
|
||||
.map(GrantedAuthority::getAuthority)
|
||||
.collect(Collectors.joining(","));
|
||||
|
||||
long now = (new Date()).getTime();
|
||||
Date validity = new Date(now + properties.getTokenValidityInSeconds());
|
||||
|
||||
return Jwts.builder()
|
||||
.setSubject(authentication.getName())
|
||||
.claim(AUTHORITIES_KEY, authorities)
|
||||
.signWith(key, SignatureAlgorithm.HS512)
|
||||
.setExpiration(validity)
|
||||
.compact();
|
||||
}
|
||||
|
||||
Authentication getAuthentication(String token) {
|
||||
Claims claims = Jwts.parser()
|
||||
.setSigningKey(key)
|
||||
.parseClaimsJws(token)
|
||||
.getBody();
|
||||
|
||||
Collection<? extends GrantedAuthority> authorities =
|
||||
Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(","))
|
||||
.map(SimpleGrantedAuthority::new)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
User principal = new User(claims.getSubject(), "", authorities);
|
||||
|
||||
return new UsernamePasswordAuthenticationToken(principal, token, authorities);
|
||||
}
|
||||
|
||||
public Date getExpirationDateFromToken(String token) {
|
||||
return getAllClaimsFromToken(token).getExpiration();
|
||||
}
|
||||
|
||||
private Claims getAllClaimsFromToken(String token) {
|
||||
return Jwts.parser()
|
||||
.setSigningKey(key)
|
||||
.parseClaimsJws(token)
|
||||
.getBody();
|
||||
}
|
||||
|
||||
boolean validateToken(String authToken) {
|
||||
try {
|
||||
Jwts.parser().setSigningKey(key).parseClaimsJws(authToken);
|
||||
return true;
|
||||
} catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) {
|
||||
log.info("Invalid JWT signature.");
|
||||
e.printStackTrace();
|
||||
} catch (ExpiredJwtException e) {
|
||||
log.info("Expired JWT token.");
|
||||
e.printStackTrace();
|
||||
} catch (UnsupportedJwtException e) {
|
||||
log.info("Unsupported JWT token.");
|
||||
e.printStackTrace();
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.info("JWT token compact of handler are invalid.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getToken(HttpServletRequest request){
|
||||
final String requestHeader = request.getHeader(properties.getHeader());
|
||||
if (requestHeader != null && requestHeader.startsWith(properties.getTokenStartWith())) {
|
||||
return requestHeader.substring(7);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package co.yixiang.modules.security.security;
|
||||
package co.yixiang.modules.security.security.vo;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@ -6,15 +6,15 @@ import lombok.Setter;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @date 2018-11-30
|
||||
* @author hupeng
|
||||
* @date 2020/01/12
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class AuthorizationUser {
|
||||
public class AuthUser {
|
||||
|
||||
@NotBlank
|
||||
private String account;
|
||||
private String username;
|
||||
|
||||
@NotBlank
|
||||
private String password;
|
||||
@ -27,6 +27,6 @@ public class AuthorizationUser {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{username=" + account + ", password= ******}";
|
||||
return "{username=" + username + ", password= ******}";
|
||||
}
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
package co.yixiang.modules.security.security;
|
||||
package co.yixiang.modules.security.security.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
@ -13,17 +14,19 @@ import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author hupeng
|
||||
* @since 2019-10-16
|
||||
* @date 2020/01/12
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class JwtUser implements UserDetails {
|
||||
|
||||
@JsonIgnore
|
||||
private final Long id;
|
||||
|
||||
private final String username;
|
||||
|
||||
private final String nickName;
|
||||
|
||||
|
||||
@JsonIgnore
|
||||
private final String password;
|
||||
|
||||
@ -36,12 +39,11 @@ public class JwtUser implements UserDetails {
|
||||
@JsonIgnore
|
||||
private final Collection<GrantedAuthority> authorities;
|
||||
|
||||
private final boolean enabled;
|
||||
|
||||
private Boolean status;
|
||||
private Integer createTime;
|
||||
|
||||
|
||||
private Integer addTime;
|
||||
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
@ -69,8 +71,10 @@ public class JwtUser implements UserDetails {
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return status;
|
||||
return enabled;
|
||||
}
|
||||
|
||||
|
||||
public Collection getRoles() {
|
||||
return authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toSet());
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package co.yixiang.modules.security.security.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author hupeng
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class OnlineUser {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String userName;
|
||||
|
||||
private String nickName;
|
||||
|
||||
private String browser;
|
||||
|
||||
private String ip;
|
||||
|
||||
private String address;
|
||||
|
||||
private String key;
|
||||
|
||||
private Date loginTime;
|
||||
|
||||
|
||||
}
|
@ -3,13 +3,15 @@ package co.yixiang.modules.security.service;
|
||||
|
||||
import co.yixiang.modules.user.entity.YxUser;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
//@CacheConfig(cacheNames = "role")
|
||||
public class JwtPermissionService {
|
||||
|
||||
|
||||
@ -18,13 +20,16 @@ public class JwtPermissionService {
|
||||
* @param user
|
||||
* @return
|
||||
*/
|
||||
//@Cacheable(key = "'loadPermissionByUser:' + #p0.username")
|
||||
|
||||
public Collection<GrantedAuthority> mapToGrantedAuthorities(YxUser user) {
|
||||
|
||||
System.out.println("--------------------loadPermissionByUser:" + user.getUsername() + "---------------------");
|
||||
|
||||
//Set<Role> roles = roleRepository.findByUsers_Id(user.getId());
|
||||
List<String> list = new ArrayList<>();
|
||||
list.add("yshop");
|
||||
|
||||
return new ArrayList<>();
|
||||
return list.stream().map(SimpleGrantedAuthority::new)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,129 @@
|
||||
package co.yixiang.modules.security.service;
|
||||
|
||||
import co.yixiang.modules.security.config.SecurityProperties;
|
||||
import co.yixiang.modules.security.security.vo.JwtUser;
|
||||
import co.yixiang.modules.security.security.vo.OnlineUser;
|
||||
import co.yixiang.utils.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author hupeng
|
||||
* @Date 2020/01/12
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class OnlineUserService {
|
||||
|
||||
private final SecurityProperties properties;
|
||||
private RedisUtils redisUtils;
|
||||
|
||||
public OnlineUserService(SecurityProperties properties, RedisUtils redisUtils) {
|
||||
this.properties = properties;
|
||||
this.redisUtils = redisUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存在线用户信息
|
||||
* @param jwtUser /
|
||||
* @param token /
|
||||
* @param request /
|
||||
*/
|
||||
public void save(JwtUser jwtUser, String token, HttpServletRequest request){
|
||||
String ip = StringUtils.getIp(request);
|
||||
String browser = StringUtils.getBrowser(request);
|
||||
String address = StringUtils.getCityInfo(ip);
|
||||
OnlineUser onlineUser = null;
|
||||
try {
|
||||
onlineUser = new OnlineUser(jwtUser.getId(),jwtUser.getUsername(), jwtUser.getNickName(), browser , ip, address, EncryptUtils.desEncrypt(token), new Date());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
redisUtils.set(properties.getOnlineKey() + token, onlineUser, properties.getTokenValidityInSeconds()/1000);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询全部数据,不分页
|
||||
* @param filter /
|
||||
* @return /
|
||||
*/
|
||||
public List<OnlineUser> getAll(String filter){
|
||||
List<String> keys = redisUtils.scan(properties.getOnlineKey() + "*");
|
||||
Collections.reverse(keys);
|
||||
List<OnlineUser> onlineUsers = new ArrayList<>();
|
||||
for (String key : keys) {
|
||||
OnlineUser onlineUser = (OnlineUser) redisUtils.get(key);
|
||||
if(StringUtils.isNotBlank(filter)){
|
||||
if(onlineUser.toString().contains(filter)){
|
||||
onlineUsers.add(onlineUser);
|
||||
}
|
||||
} else {
|
||||
onlineUsers.add(onlineUser);
|
||||
}
|
||||
}
|
||||
onlineUsers.sort((o1, o2) -> o2.getLoginTime().compareTo(o1.getLoginTime()));
|
||||
return onlineUsers;
|
||||
}
|
||||
|
||||
/**
|
||||
* 踢出用户
|
||||
* @param key /
|
||||
* @throws Exception /
|
||||
*/
|
||||
public void kickOut(String key) throws Exception {
|
||||
key = properties.getOnlineKey() + EncryptUtils.desDecrypt(key);
|
||||
redisUtils.del(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
* @param token /
|
||||
*/
|
||||
public void logout(String token) {
|
||||
String key = properties.getOnlineKey() + token;
|
||||
redisUtils.del(key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询用户
|
||||
* @param key /
|
||||
* @return /
|
||||
*/
|
||||
public OnlineUser getOne(String key) {
|
||||
return (OnlineUser)redisUtils.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测用户是否在之前已经登录,已经登录踢下线
|
||||
* @param userName 用户名
|
||||
*/
|
||||
public void checkLoginOnUser(String userName, String igoreToken){
|
||||
List<OnlineUser> onlineUsers = getAll(userName);
|
||||
if(onlineUsers ==null || onlineUsers.isEmpty()){
|
||||
return;
|
||||
}
|
||||
for(OnlineUser onlineUser:onlineUsers){
|
||||
if(onlineUser.getUserName().equals(userName)){
|
||||
try {
|
||||
String token =EncryptUtils.desDecrypt(onlineUser.getKey());
|
||||
if(StringUtils.isNotBlank(igoreToken)&&!igoreToken.equals(token)){
|
||||
this.kickOut(onlineUser.getKey());
|
||||
}else if(StringUtils.isBlank(igoreToken)){
|
||||
this.kickOut(onlineUser.getKey());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("checkUser is error",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,47 +1,53 @@
|
||||
package co.yixiang.modules.security.service;
|
||||
|
||||
import co.yixiang.exception.BadRequestException;
|
||||
import co.yixiang.modules.security.security.JwtUser;
|
||||
import co.yixiang.modules.security.security.vo.JwtUser;
|
||||
import co.yixiang.modules.user.entity.YxUser;
|
||||
import co.yixiang.modules.user.service.YxUserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author hupeng
|
||||
* @since 2019-10-16
|
||||
* @date 2020/01/12
|
||||
*/
|
||||
@Service
|
||||
@Service("userDetailsService")
|
||||
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
|
||||
public class JwtUserDetailsService implements UserDetailsService {
|
||||
public class UserDetailsServiceImpl implements UserDetailsService {
|
||||
|
||||
private final YxUserService userService;
|
||||
private final JwtPermissionService permissionService;
|
||||
|
||||
|
||||
@Autowired
|
||||
private YxUserService yxUserService;
|
||||
|
||||
@Autowired
|
||||
private JwtPermissionService permissionService;
|
||||
public UserDetailsServiceImpl(YxUserService userService,JwtPermissionService permissionService) {
|
||||
this.userService = userService;
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username){
|
||||
System.out.println("username2:"+username);
|
||||
YxUser user = yxUserService.findByName(username);
|
||||
YxUser user = userService.findByName(username);
|
||||
if (user == null) {
|
||||
throw new BadRequestException(HttpStatus.UNAUTHORIZED,"账号不存在");
|
||||
throw new BadRequestException("账号不存在");
|
||||
} else {
|
||||
if (!user.getStatus()) {
|
||||
throw new BadRequestException("账号未激活");
|
||||
}
|
||||
return createJwtUser(user);
|
||||
}
|
||||
}
|
||||
|
||||
public UserDetails createJwtUser(YxUser user) {
|
||||
private UserDetails createJwtUser(YxUser user) {
|
||||
return new JwtUser(
|
||||
user.getUid().longValue(),
|
||||
Long.valueOf(user.getUid()),
|
||||
user.getUsername(),
|
||||
user.getNickname(),
|
||||
user.getPassword(),
|
||||
user.getAvatar(),
|
||||
user.getPhone(),
|
@ -1,123 +0,0 @@
|
||||
package co.yixiang.modules.security.utils;
|
||||
|
||||
import co.yixiang.modules.security.security.JwtUser;
|
||||
import io.jsonwebtoken.*;
|
||||
import io.jsonwebtoken.impl.DefaultClock;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Component
|
||||
public class JwtTokenUtil implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -3301605591108950415L;
|
||||
private Clock clock = DefaultClock.INSTANCE;
|
||||
|
||||
@Value("${jwt.secret}")
|
||||
private String secret;
|
||||
|
||||
@Value("${jwt.expiration}")
|
||||
private Long expiration;
|
||||
|
||||
@Value("${jwt.header}")
|
||||
private String tokenHeader;
|
||||
|
||||
public String getUsernameFromToken(String token) {
|
||||
return getClaimFromToken(token, Claims::getSubject);
|
||||
}
|
||||
|
||||
public Date getIssuedAtDateFromToken(String token) {
|
||||
return getClaimFromToken(token, Claims::getIssuedAt);
|
||||
}
|
||||
|
||||
public Date getExpirationDateFromToken(String token) {
|
||||
return getClaimFromToken(token, Claims::getExpiration);
|
||||
}
|
||||
|
||||
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
|
||||
final Claims claims = getAllClaimsFromToken(token);
|
||||
return claimsResolver.apply(claims);
|
||||
}
|
||||
|
||||
private Claims getAllClaimsFromToken(String token) {
|
||||
return Jwts.parser()
|
||||
.setSigningKey(secret)
|
||||
.parseClaimsJws(token)
|
||||
.getBody();
|
||||
}
|
||||
|
||||
private Boolean isTokenExpired(String token) {
|
||||
final Date expiration = getExpirationDateFromToken(token);
|
||||
return expiration.before(clock.now());
|
||||
}
|
||||
|
||||
private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) {
|
||||
return (lastPasswordReset != null && created.before(lastPasswordReset));
|
||||
}
|
||||
|
||||
private Boolean ignoreTokenExpiration(String token) {
|
||||
// here you specify tokens, for that the expiration is ignored
|
||||
return false;
|
||||
}
|
||||
|
||||
public String generateToken(UserDetails userDetails) {
|
||||
Map<String, Object> claims = new HashMap<>();
|
||||
return doGenerateToken(claims, userDetails.getUsername());
|
||||
}
|
||||
|
||||
private String doGenerateToken(Map<String, Object> claims, String subject) {
|
||||
final Date createdDate = clock.now();
|
||||
final Date expirationDate = calculateExpirationDate(createdDate);
|
||||
|
||||
return Jwts.builder()
|
||||
.setClaims(claims)
|
||||
.setSubject(subject)
|
||||
.setIssuedAt(createdDate)
|
||||
.setExpiration(expirationDate)
|
||||
.signWith(SignatureAlgorithm.HS512, secret)
|
||||
.compact();
|
||||
}
|
||||
|
||||
public Boolean canTokenBeRefreshed(String token, Date lastPasswordReset) {
|
||||
final Date created = getIssuedAtDateFromToken(token);
|
||||
return !isCreatedBeforeLastPasswordReset(created, lastPasswordReset)
|
||||
&& (!isTokenExpired(token) || ignoreTokenExpiration(token));
|
||||
}
|
||||
|
||||
public String refreshToken(String token) {
|
||||
final Date createdDate = clock.now();
|
||||
final Date expirationDate = calculateExpirationDate(createdDate);
|
||||
|
||||
final Claims claims = getAllClaimsFromToken(token);
|
||||
claims.setIssuedAt(createdDate);
|
||||
claims.setExpiration(expirationDate);
|
||||
|
||||
return Jwts.builder()
|
||||
.setClaims(claims)
|
||||
.signWith(SignatureAlgorithm.HS512, secret)
|
||||
.compact();
|
||||
}
|
||||
|
||||
public Boolean validateToken(String token, UserDetails userDetails) {
|
||||
JwtUser user = (JwtUser) userDetails;
|
||||
final Date created = getIssuedAtDateFromToken(token);
|
||||
// final Date expiration = getExpirationDateFromToken(token);
|
||||
// 如果token存在,且token创建日期 > 最后修改密码的日期 则代表token有效
|
||||
// return (!isTokenExpired(token)
|
||||
// && !isCreatedBeforeLastPasswordReset(created, user.getLastPasswordResetDate())
|
||||
// );
|
||||
|
||||
return !isTokenExpired(token);
|
||||
}
|
||||
|
||||
private Date calculateExpirationDate(Date createdDate) {
|
||||
return new Date(createdDate.getTime() + expiration);
|
||||
}
|
||||
}
|
||||
|
@ -1,199 +0,0 @@
|
||||
package co.yixiang.modules.security.utils;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* @author https://blog.csdn.net/ruixue0117/article/details/22829557
|
||||
* @date 2019-6-20 17:28:53
|
||||
*/
|
||||
public class VerifyCodeUtils{
|
||||
|
||||
//使用到Algerian字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,i,o几个容易混淆的字符
|
||||
public static final String VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
|
||||
private static Random random = new Random();
|
||||
|
||||
|
||||
/**
|
||||
* 使用系统默认字符源生成验证码
|
||||
* @param verifySize 验证码长度
|
||||
* @return
|
||||
*/
|
||||
public static String generateVerifyCode(int verifySize){
|
||||
return generateVerifyCode(verifySize, VERIFY_CODES);
|
||||
}
|
||||
/**
|
||||
* 使用指定源生成验证码
|
||||
* @param verifySize 验证码长度
|
||||
* @param sources 验证码字符源
|
||||
* @return
|
||||
*/
|
||||
public static String generateVerifyCode(int verifySize, String sources){
|
||||
if(sources == null || sources.length() == 0){
|
||||
sources = VERIFY_CODES;
|
||||
}
|
||||
int codesLen = sources.length();
|
||||
Random rand = new Random(System.currentTimeMillis());
|
||||
StringBuilder verifyCode = new StringBuilder(verifySize);
|
||||
for(int i = 0; i < verifySize; i++){
|
||||
verifyCode.append(sources.charAt(rand.nextInt(codesLen-1)));
|
||||
}
|
||||
return verifyCode.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出指定验证码图片流
|
||||
* @param w
|
||||
* @param h
|
||||
* @param os
|
||||
* @param code
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void outputImage(int w, int h, OutputStream os, String code) throws IOException{
|
||||
int verifySize = code.length();
|
||||
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
|
||||
Random rand = new Random();
|
||||
Graphics2D g2 = image.createGraphics();
|
||||
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
Color[] colors = new Color[5];
|
||||
Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN,
|
||||
Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,
|
||||
Color.PINK, Color.YELLOW };
|
||||
float[] fractions = new float[colors.length];
|
||||
for(int i = 0; i < colors.length; i++){
|
||||
colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
|
||||
fractions[i] = rand.nextFloat();
|
||||
}
|
||||
Arrays.sort(fractions);
|
||||
|
||||
g2.setColor(Color.GRAY);// 设置边框色
|
||||
g2.fillRect(0, 0, w, h);
|
||||
|
||||
Color c = getRandColor(200, 250);
|
||||
g2.setColor(c);// 设置背景色
|
||||
g2.fillRect(0, 2, w, h-4);
|
||||
|
||||
//绘制干扰线
|
||||
Random random = new Random();
|
||||
g2.setColor(getRandColor(160, 200));// 设置线条的颜色
|
||||
for (int i = 0; i < 20; i++) {
|
||||
int x = random.nextInt(w - 1);
|
||||
int y = random.nextInt(h - 1);
|
||||
int xl = random.nextInt(6) + 1;
|
||||
int yl = random.nextInt(12) + 1;
|
||||
g2.drawLine(x, y, x + xl + 40, y + yl + 20);
|
||||
}
|
||||
|
||||
// 添加噪点
|
||||
float yawpRate = 0.05f;// 噪声率
|
||||
int area = (int) (yawpRate * w * h);
|
||||
for (int i = 0; i < area; i++) {
|
||||
int x = random.nextInt(w);
|
||||
int y = random.nextInt(h);
|
||||
int rgb = getRandomIntColor();
|
||||
image.setRGB(x, y, rgb);
|
||||
}
|
||||
|
||||
shear(g2, w, h, c);// 使图片扭曲
|
||||
|
||||
g2.setColor(getRandColor(100, 160));
|
||||
int fontSize = h-4;
|
||||
Font font = new Font("Algerian", Font.ITALIC, fontSize);
|
||||
g2.setFont(font);
|
||||
char[] chars = code.toCharArray();
|
||||
for(int i = 0; i < verifySize; i++){
|
||||
AffineTransform affine = new AffineTransform();
|
||||
affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize/2, h/2);
|
||||
g2.setTransform(affine);
|
||||
g2.drawChars(chars, i, 1, ((w-10) / verifySize) * i + 5, h/2 + fontSize/2 - 10);
|
||||
}
|
||||
|
||||
g2.dispose();
|
||||
ImageIO.write(image, "jpg", os);
|
||||
}
|
||||
|
||||
private static Color getRandColor(int fc, int bc) {
|
||||
if (fc > 255)
|
||||
fc = 255;
|
||||
if (bc > 255)
|
||||
bc = 255;
|
||||
int r = fc + random.nextInt(bc - fc);
|
||||
int g = fc + random.nextInt(bc - fc);
|
||||
int b = fc + random.nextInt(bc - fc);
|
||||
return new Color(r, g, b);
|
||||
}
|
||||
|
||||
private static int getRandomIntColor() {
|
||||
int[] rgb = getRandomRgb();
|
||||
int color = 0;
|
||||
for (int c : rgb) {
|
||||
color = color << 8;
|
||||
color = color | c;
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
private static int[] getRandomRgb() {
|
||||
int[] rgb = new int[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
rgb[i] = random.nextInt(255);
|
||||
}
|
||||
return rgb;
|
||||
}
|
||||
|
||||
private static void shear(Graphics g, int w1, int h1, Color color) {
|
||||
shearX(g, w1, h1, color);
|
||||
shearY(g, w1, h1, color);
|
||||
}
|
||||
|
||||
private static void shearX(Graphics g, int w1, int h1, Color color) {
|
||||
|
||||
int period = random.nextInt(2);
|
||||
|
||||
boolean borderGap = true;
|
||||
int frames = 1;
|
||||
int phase = random.nextInt(2);
|
||||
|
||||
for (int i = 0; i < h1; i++) {
|
||||
double d = (double) (period >> 1)
|
||||
* Math.sin((double) i / (double) period
|
||||
+ (6.2831853071795862D * (double) phase)
|
||||
/ (double) frames);
|
||||
g.copyArea(0, i, w1, 1, (int) d, 0);
|
||||
if (borderGap) {
|
||||
g.setColor(color);
|
||||
g.drawLine((int) d, i, 0, i);
|
||||
g.drawLine((int) d + w1, i, w1, i);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void shearY(Graphics g, int w1, int h1, Color color) {
|
||||
|
||||
int period = random.nextInt(40) + 10; // 50;
|
||||
|
||||
boolean borderGap = true;
|
||||
int frames = 20;
|
||||
int phase = 7;
|
||||
for (int i = 0; i < w1; i++) {
|
||||
double d = (double) (period >> 1)
|
||||
* Math.sin((double) i / (double) period
|
||||
+ (6.2831853071795862D * (double) phase)
|
||||
/ (double) frames);
|
||||
g.copyArea(i, 0, 1, h1, 0, (int) d);
|
||||
if (borderGap) {
|
||||
g.setColor(color);
|
||||
g.drawLine(i, (int) d, i, 0);
|
||||
g.drawLine(i, (int) d + h1, i, h1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package co.yixiang.modules.shop.web.controller;
|
||||
|
||||
import co.yixiang.annotation.AnonymousAccess;
|
||||
import co.yixiang.common.api.ApiResult;
|
||||
import co.yixiang.common.web.controller.BaseController;
|
||||
import co.yixiang.common.web.vo.Paging;
|
||||
@ -33,6 +34,7 @@ public class ArticleController extends BaseController {
|
||||
/**
|
||||
* 获取文章文章详情
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@GetMapping("/details/{id}")
|
||||
@ApiOperation(value = "文章详情",notes = "文章详情",response = YxArticleQueryVo.class)
|
||||
public ApiResult<YxArticleQueryVo> getYxArticle(@PathVariable Integer id) throws Exception{
|
||||
@ -44,6 +46,7 @@ public class ArticleController extends BaseController {
|
||||
/**
|
||||
* 文章列表
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@GetMapping("/list")
|
||||
@ApiOperation(value = "文章列表",notes = "文章列表",response = YxArticleQueryVo.class)
|
||||
public ApiResult<Paging<YxArticleQueryVo>> getYxArticlePageList(
|
||||
|
@ -1,5 +1,6 @@
|
||||
package co.yixiang.modules.shop.web.controller;
|
||||
|
||||
import co.yixiang.annotation.AnonymousAccess;
|
||||
import co.yixiang.common.api.ApiResult;
|
||||
import co.yixiang.modules.shop.service.YxStoreProductService;
|
||||
import co.yixiang.modules.shop.service.YxSystemConfigService;
|
||||
@ -34,6 +35,7 @@ public class IndexController {
|
||||
|
||||
|
||||
|
||||
@AnonymousAccess
|
||||
@GetMapping("/index")
|
||||
@ApiOperation(value = "首页数据",notes = "首页数据")
|
||||
public ApiResult<Map<String,Object>> index(){
|
||||
@ -66,6 +68,7 @@ public class IndexController {
|
||||
return ApiResult.ok(map);
|
||||
}
|
||||
|
||||
@AnonymousAccess
|
||||
@GetMapping("/search/keyword")
|
||||
@ApiOperation(value = "热门搜索关键字获取",notes = "热门搜索关键字获取")
|
||||
public ApiResult<List<String>> search(){
|
||||
@ -78,6 +81,7 @@ public class IndexController {
|
||||
return ApiResult.ok(stringList);
|
||||
}
|
||||
|
||||
@AnonymousAccess
|
||||
@PostMapping("/image_base64")
|
||||
@ApiOperation(value = "获取图片base64",notes = "获取图片base64")
|
||||
public ApiResult<List<String>> imageBase64(){
|
||||
|
@ -1,5 +1,6 @@
|
||||
package co.yixiang.modules.shop.web.controller;
|
||||
|
||||
import co.yixiang.annotation.AnonymousAccess;
|
||||
import co.yixiang.common.api.ApiResult;
|
||||
import co.yixiang.common.web.controller.BaseController;
|
||||
import co.yixiang.common.web.vo.Paging;
|
||||
@ -32,6 +33,7 @@ public class StoreCategoryController extends BaseController {
|
||||
/**
|
||||
* 商品分类列表
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@GetMapping("/category")
|
||||
@ApiOperation(value = "商品分类列表",notes = "商品分类列表")
|
||||
public ApiResult<Paging<YxStoreCategoryQueryVo>> getYxStoreCategoryPageList(){
|
||||
|
@ -1,5 +1,6 @@
|
||||
package co.yixiang.modules.shop.web.controller;
|
||||
|
||||
import co.yixiang.annotation.AnonymousAccess;
|
||||
import co.yixiang.aop.log.Log;
|
||||
import co.yixiang.common.api.ApiResult;
|
||||
import co.yixiang.common.web.controller.BaseController;
|
||||
@ -45,6 +46,7 @@ public class StoreProductController extends BaseController {
|
||||
/**
|
||||
* 获取首页更多产品
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@GetMapping("/groom/list/{type}")
|
||||
@ApiOperation(value = "获取首页更多产品",notes = "获取首页更多产品")
|
||||
public ApiResult<Map<String,Object>> moreGoodsList(@PathVariable Integer type){
|
||||
@ -66,6 +68,7 @@ public class StoreProductController extends BaseController {
|
||||
/**
|
||||
* 获取首页更多产品
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@GetMapping("/products")
|
||||
@ApiOperation(value = "商品列表",notes = "商品列表")
|
||||
public ApiResult<List<YxStoreProductQueryVo>> goodsList(YxStoreProductQueryParam productQueryParam){
|
||||
@ -76,6 +79,7 @@ public class StoreProductController extends BaseController {
|
||||
/**
|
||||
* 为你推荐
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@GetMapping("/product/hot")
|
||||
@ApiOperation(value = "为你推荐",notes = "为你推荐")
|
||||
public ApiResult<List<YxStoreProductQueryVo>> productRecommend(
|
||||
|
@ -1,5 +1,6 @@
|
||||
package co.yixiang.modules.user.web.controller;
|
||||
|
||||
import co.yixiang.annotation.AnonymousAccess;
|
||||
import co.yixiang.aop.log.Log;
|
||||
import co.yixiang.common.api.ApiResult;
|
||||
import co.yixiang.common.web.controller.BaseController;
|
||||
@ -134,6 +135,7 @@ public class UserController extends BaseController {
|
||||
/**
|
||||
* 获取活动状态
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@GetMapping("/user/activity")
|
||||
@ApiOperation(value = "获取活动状态",notes = "获取活动状态")
|
||||
public ApiResult<Object> activity(){
|
||||
|
@ -3,14 +3,13 @@ package co.yixiang.modules.wechat.web.controller;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import co.yixiang.annotation.AnonymousAccess;
|
||||
import co.yixiang.common.api.ApiCode;
|
||||
import co.yixiang.common.api.ApiResult;
|
||||
import co.yixiang.common.web.controller.BaseController;
|
||||
import co.yixiang.modules.order.entity.YxStoreOrder;
|
||||
import co.yixiang.modules.order.service.YxStoreOrderService;
|
||||
import co.yixiang.modules.order.web.vo.YxStoreOrderQueryVo;
|
||||
import co.yixiang.modules.security.security.JwtUser;
|
||||
import co.yixiang.modules.security.utils.JwtTokenUtil;
|
||||
import co.yixiang.modules.shop.service.YxSystemConfigService;
|
||||
import co.yixiang.modules.user.entity.YxUser;
|
||||
import co.yixiang.modules.user.entity.YxWechatUser;
|
||||
@ -69,17 +68,11 @@ public class WechatController extends BaseController {
|
||||
private final WxMpMessageRouter messageRouter;
|
||||
private final YxSystemConfigService systemConfigService;
|
||||
|
||||
@Autowired
|
||||
private JwtTokenUtil jwtTokenUtil;
|
||||
|
||||
|
||||
@Autowired
|
||||
@Qualifier("jwtUserDetailsService")
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
/**
|
||||
* 微信分享配置
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@GetMapping("/share")
|
||||
@ApiOperation(value = "微信分享配置",notes = "微信分享配置")
|
||||
public ApiResult<Object> share() {
|
||||
@ -95,131 +88,19 @@ public class WechatController extends BaseController {
|
||||
/**
|
||||
* jssdk配置
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@GetMapping("/wechat/config")
|
||||
@ApiOperation(value = "jssdk配置",notes = "jssdk配置")
|
||||
public ApiResult<Object> jsConfig(@RequestParam(value = "url") String url) throws WxErrorException {
|
||||
return ApiResult.ok(wxService.createJsapiSignature(url));
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信授权
|
||||
*/
|
||||
@GetMapping("/wechat/auth")
|
||||
@ApiOperation(value = "微信授权",notes = "微信授权")
|
||||
public ApiResult<Object> authLogin(@RequestParam(value = "code") String code,
|
||||
@RequestParam(value = "spread") String spread) {
|
||||
|
||||
try {
|
||||
WxMpOAuth2AccessToken wxMpOAuth2AccessToken = wxService.oauth2getAccessToken(code);
|
||||
WxMpUser wxMpUser = wxService.oauth2getUserInfo(wxMpOAuth2AccessToken, null);
|
||||
String openid = wxMpUser.getOpenId();
|
||||
YxWechatUser wechatUser = wechatUserService.getUserInfo(openid);
|
||||
|
||||
|
||||
JwtUser jwtUser = null;
|
||||
if(ObjectUtil.isNotNull(wechatUser)){
|
||||
YxUserQueryVo yxUserQueryVo = userService.getYxUserById(wechatUser.getUid());
|
||||
if(ObjectUtil.isNotNull(yxUserQueryVo)){
|
||||
jwtUser = (JwtUser) userDetailsService.loadUserByUsername(wechatUser.getOpenid());
|
||||
}else{
|
||||
if(ObjectUtil.isNotNull(wechatUser)){
|
||||
wechatUserService.removeById(wechatUser.getUid());
|
||||
}
|
||||
if(ObjectUtil.isNotNull(yxUserQueryVo)){
|
||||
userService.removeById(yxUserQueryVo.getUid());
|
||||
}
|
||||
return ApiResult.fail(ApiCode.FAIL_AUTH,"授权失败");
|
||||
}
|
||||
|
||||
|
||||
}else{
|
||||
|
||||
//过滤掉表情
|
||||
String nickname = EmojiParser.removeAllEmojis(wxMpUser.getNickname());
|
||||
log.info("昵称:{}",nickname);
|
||||
//用户保存
|
||||
YxUser user = new YxUser();
|
||||
user.setAccount(nickname);
|
||||
user.setUsername(wxMpUser.getOpenId());
|
||||
user.setPassword(EncryptUtils.encryptPassword("123456"));
|
||||
user.setPwd(EncryptUtils.encryptPassword("123456"));
|
||||
user.setPhone("");
|
||||
user.setUserType("wechat");
|
||||
user.setAddTime(OrderUtil.getSecondTimestampTwo());
|
||||
user.setLastTime(OrderUtil.getSecondTimestampTwo());
|
||||
user.setNickname(nickname);
|
||||
user.setAvatar(wxMpUser.getHeadImgUrl());
|
||||
user.setNowMoney(BigDecimal.ZERO);
|
||||
user.setBrokeragePrice(BigDecimal.ZERO);
|
||||
user.setIntegral(BigDecimal.ZERO);
|
||||
|
||||
userService.save(user);
|
||||
|
||||
|
||||
//保存微信用户
|
||||
YxWechatUser yxWechatUser = new YxWechatUser();
|
||||
yxWechatUser.setAddTime(OrderUtil.getSecondTimestampTwo());
|
||||
yxWechatUser.setNickname(nickname);
|
||||
yxWechatUser.setOpenid(wxMpUser.getOpenId());
|
||||
int sub = 0;
|
||||
if(ObjectUtil.isNotNull(wxMpUser.getSubscribe()) && wxMpUser.getSubscribe()) sub =1;
|
||||
yxWechatUser.setSubscribe(sub);
|
||||
yxWechatUser.setSex(wxMpUser.getSex());
|
||||
yxWechatUser.setLanguage(wxMpUser.getLanguage());
|
||||
yxWechatUser.setCity(wxMpUser.getCity());
|
||||
yxWechatUser.setProvince(wxMpUser.getProvince());
|
||||
yxWechatUser.setCountry(wxMpUser.getCountry());
|
||||
yxWechatUser.setHeadimgurl(wxMpUser.getHeadImgUrl());
|
||||
if(ObjectUtil.isNotNull(wxMpUser.getSubscribeTime())){
|
||||
yxWechatUser.setSubscribeTime(wxMpUser.getSubscribeTime().intValue());
|
||||
}
|
||||
if(StrUtil.isNotEmpty(wxMpUser.getUnionId())){
|
||||
yxWechatUser.setUnionid(wxMpUser.getUnionId());
|
||||
}
|
||||
if(StrUtil.isNotEmpty(wxMpUser.getRemark())){
|
||||
yxWechatUser.setUnionid(wxMpUser.getRemark());
|
||||
}
|
||||
if(ObjectUtil.isNotEmpty(wxMpUser.getGroupId())){
|
||||
yxWechatUser.setGroupid(wxMpUser.getGroupId());
|
||||
}
|
||||
yxWechatUser.setUid(user.getUid());
|
||||
|
||||
wechatUserService.save(yxWechatUser);
|
||||
|
||||
|
||||
|
||||
jwtUser = (JwtUser) userDetailsService.loadUserByUsername(wxMpUser.getOpenId());
|
||||
}
|
||||
|
||||
|
||||
//设置推广关系
|
||||
if(StrUtil.isNotEmpty(spread) && !spread.equals("NaN")){
|
||||
//System.out.println("spread:"+spread);
|
||||
userService.setSpread(Integer.valueOf(spread),
|
||||
jwtUser.getId().intValue());
|
||||
}
|
||||
|
||||
// 生成令牌
|
||||
final String token = jwtTokenUtil.generateToken(jwtUser);
|
||||
Date expiresTime = jwtTokenUtil.getExpirationDateFromToken(token);
|
||||
String expiresTimeStr = DateUtil.formatDateTime(expiresTime);
|
||||
Map<String,String> map = new LinkedHashMap<>();
|
||||
map.put("token",token);
|
||||
map.put("expires_time",expiresTimeStr);
|
||||
|
||||
// 返回 token
|
||||
return ApiResult.ok(map);
|
||||
} catch (WxErrorException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
return ApiResult.fail("授权失败");
|
||||
}
|
||||
// return ApiResult.ok(wxService.createJsapiSignature(url));
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信支付回调
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@PostMapping("/wechat/notify")
|
||||
@ApiOperation(value = "微信支付回调",notes = "微信支付回调")
|
||||
public String notify(@RequestBody String xmlData) {
|
||||
@ -247,6 +128,7 @@ public class WechatController extends BaseController {
|
||||
* @return
|
||||
* @throws WxPayException
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@ApiOperation(value = "退款回调通知处理",notes = "退款回调通知处理")
|
||||
@PostMapping("/notify/refund")
|
||||
public String parseRefundNotifyResult(@RequestBody String xmlData) {
|
||||
@ -275,6 +157,7 @@ public class WechatController extends BaseController {
|
||||
/**
|
||||
* 微信验证消息
|
||||
*/
|
||||
@AnonymousAccess
|
||||
@GetMapping("/wechat/serve")
|
||||
@ApiOperation(value = "微信验证消息",notes = "微信验证消息")
|
||||
public String authGet(@RequestParam(name = "signature", required = false) String signature,
|
||||
@ -290,7 +173,9 @@ public class WechatController extends BaseController {
|
||||
}
|
||||
|
||||
|
||||
@AnonymousAccess
|
||||
@PostMapping("/wechat/serve")
|
||||
@ApiOperation(value = "微信获取消息",notes = "微信获取消息")
|
||||
public void post(@RequestBody String requestBody,
|
||||
@RequestParam("signature") String signature,
|
||||
@RequestParam("timestamp") String timestamp,
|
||||
|
@ -1,45 +1,13 @@
|
||||
package co.yixiang.modules.wechat.web.controller;
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
|
||||
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import co.yixiang.common.api.ApiCode;
|
||||
import co.yixiang.common.api.ApiResult;
|
||||
import co.yixiang.exception.ErrorRequestException;
|
||||
import co.yixiang.modules.security.security.JwtUser;
|
||||
import co.yixiang.modules.security.utils.JwtTokenUtil;
|
||||
import co.yixiang.modules.user.entity.YxUser;
|
||||
import co.yixiang.modules.user.entity.YxWechatUser;
|
||||
import co.yixiang.modules.user.service.YxUserService;
|
||||
import co.yixiang.modules.user.service.YxWechatUserService;
|
||||
import co.yixiang.modules.user.web.vo.YxUserQueryVo;
|
||||
import co.yixiang.utils.EncryptUtils;
|
||||
import co.yixiang.utils.OrderUtil;
|
||||
import co.yixiang.utils.RedisUtil;
|
||||
import com.vdurmont.emoji.EmojiParser;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 微信小程序用户接口
|
||||
*
|
||||
@ -49,132 +17,11 @@ import java.util.Map;
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
|
||||
@Api(value = "微信小程序", tags = "微信小程序", description = "微信小程序")
|
||||
public class WxMaUserController {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
private final WxMaService wxMaService;
|
||||
private final YxWechatUserService wechatUserService;
|
||||
private final YxUserService userService;
|
||||
private final JwtTokenUtil jwtTokenUtil;
|
||||
|
||||
|
||||
@Autowired
|
||||
@Qualifier("jwtUserDetailsService")
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
/**
|
||||
* 小程序登陆接口
|
||||
*/
|
||||
@PostMapping("/wxapp/auth")
|
||||
@ApiOperation(value = "小程序登陆",notes = "小程序登陆")
|
||||
public ApiResult<Object> login(@RequestParam(value = "code") String code,
|
||||
@RequestParam(value = "spread") String spread,
|
||||
@RequestParam(value = "encryptedData") String encryptedData,
|
||||
@RequestParam(value = "iv") String iv ) {
|
||||
if (StringUtils.isBlank(code)) {
|
||||
return ApiResult.fail("请传code");
|
||||
}
|
||||
try {
|
||||
//读取redis配置
|
||||
String appId = RedisUtil.get("wxapp_appId");
|
||||
String secret = RedisUtil.get("wxapp_secret");
|
||||
if(StrUtil.isBlank(appId) || StrUtil.isBlank(secret)){
|
||||
throw new ErrorRequestException("请先配置小程序");
|
||||
}
|
||||
WxMaDefaultConfigImpl wxMaConfig = new WxMaDefaultConfigImpl();
|
||||
wxMaConfig.setAppid(appId);
|
||||
wxMaConfig.setSecret(secret);
|
||||
|
||||
|
||||
wxMaService.setWxMaConfig(wxMaConfig);
|
||||
WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(code);
|
||||
YxWechatUser wechatUser = wechatUserService.getUserInfo(session.getOpenid());;
|
||||
JwtUser jwtUser = null;
|
||||
if(ObjectUtil.isNotNull(wechatUser)){
|
||||
YxUserQueryVo yxUserQueryVo = userService.getYxUserById(wechatUser.getUid());
|
||||
if(ObjectUtil.isNotNull(yxUserQueryVo)){
|
||||
jwtUser = (JwtUser) userDetailsService.loadUserByUsername(wechatUser.getOpenid());
|
||||
}else{
|
||||
if(ObjectUtil.isNotNull(wechatUser)){
|
||||
wechatUserService.removeById(wechatUser.getUid());
|
||||
}
|
||||
if(ObjectUtil.isNotNull(yxUserQueryVo)){
|
||||
userService.removeById(yxUserQueryVo.getUid());
|
||||
}
|
||||
return ApiResult.fail(ApiCode.FAIL_AUTH,"授权失败");
|
||||
}
|
||||
|
||||
}else{
|
||||
WxMaUserInfo wxMpUser = wxMaService.getUserService()
|
||||
.getUserInfo(session.getSessionKey(), encryptedData, iv);
|
||||
//过滤掉表情
|
||||
String nickname = EmojiParser.removeAllEmojis(wxMpUser.getNickName());
|
||||
//用户保存
|
||||
YxUser user = new YxUser();
|
||||
user.setAccount(nickname);
|
||||
user.setUsername(wxMpUser.getOpenId());
|
||||
user.setPassword(EncryptUtils.encryptPassword("123456"));
|
||||
user.setPwd(EncryptUtils.encryptPassword("123456"));
|
||||
user.setPhone("");
|
||||
user.setUserType("routine");
|
||||
user.setAddTime(OrderUtil.getSecondTimestampTwo());
|
||||
user.setLastTime(OrderUtil.getSecondTimestampTwo());
|
||||
user.setNickname(nickname);
|
||||
user.setAvatar(wxMpUser.getAvatarUrl());
|
||||
user.setNowMoney(BigDecimal.ZERO);
|
||||
user.setBrokeragePrice(BigDecimal.ZERO);
|
||||
user.setIntegral(BigDecimal.ZERO);
|
||||
|
||||
userService.save(user);
|
||||
|
||||
|
||||
//保存微信用户
|
||||
YxWechatUser yxWechatUser = new YxWechatUser();
|
||||
// System.out.println("wxMpUser:"+wxMpUser);
|
||||
yxWechatUser.setAddTime(OrderUtil.getSecondTimestampTwo());
|
||||
yxWechatUser.setNickname(nickname);
|
||||
yxWechatUser.setRoutineOpenid(wxMpUser.getOpenId());
|
||||
int sub = 0;
|
||||
yxWechatUser.setSubscribe(sub);
|
||||
yxWechatUser.setSex(Integer.valueOf(wxMpUser.getGender()));
|
||||
yxWechatUser.setLanguage(wxMpUser.getLanguage());
|
||||
yxWechatUser.setCity(wxMpUser.getCity());
|
||||
yxWechatUser.setProvince(wxMpUser.getProvince());
|
||||
yxWechatUser.setCountry(wxMpUser.getCountry());
|
||||
yxWechatUser.setHeadimgurl(wxMpUser.getAvatarUrl());
|
||||
if(StrUtil.isNotEmpty(wxMpUser.getUnionId())){
|
||||
yxWechatUser.setUnionid(wxMpUser.getUnionId());
|
||||
}
|
||||
yxWechatUser.setUid(user.getUid());
|
||||
|
||||
wechatUserService.save(yxWechatUser);
|
||||
|
||||
|
||||
jwtUser = (JwtUser) userDetailsService.loadUserByUsername(wxMpUser.getOpenId());
|
||||
}
|
||||
|
||||
|
||||
//设置推广关系
|
||||
if(StrUtil.isNotEmpty(spread)){
|
||||
//System.out.println("spread:"+spread);
|
||||
userService.setSpread(Integer.valueOf(spread),
|
||||
jwtUser.getId().intValue());
|
||||
}
|
||||
|
||||
// 生成令牌
|
||||
final String token = jwtTokenUtil.generateToken(jwtUser);
|
||||
Date expiresTime = jwtTokenUtil.getExpirationDateFromToken(token);
|
||||
String expiresTimeStr = DateUtil.formatDateTime(expiresTime);
|
||||
Map<String,String> map = new LinkedHashMap<>();
|
||||
map.put("token",token);
|
||||
map.put("expires_time",expiresTimeStr);
|
||||
|
||||
// 返回 token
|
||||
return ApiResult.ok(map);
|
||||
} catch (WxErrorException e) {
|
||||
this.logger.error(e.getMessage(), e);
|
||||
return ApiResult.fail(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// /**
|
||||
// * <pre>
|
||||
@ -182,7 +29,7 @@ public class WxMaUserController {
|
||||
// * </pre>
|
||||
// */
|
||||
// @GetMapping("/phone")
|
||||
// public String phone(@PathVariable String appid, String sessionKey, String signature,
|
||||
// public String phone(String sessionKey, String signature,
|
||||
// String rawData, String encryptedData, String iv) {
|
||||
//
|
||||
// // 用户信息校验
|
||||
@ -196,4 +43,6 @@ public class WxMaUserController {
|
||||
// return JsonUtils.toJson(phoneNoInfo);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -51,21 +51,19 @@ spring:
|
||||
#连接超时时间
|
||||
timeout: 5000
|
||||
|
||||
#jwt
|
||||
#jwt
|
||||
jwt:
|
||||
header: Authorization
|
||||
secret: JBqNQX7HD9xhwHP7
|
||||
# 令牌前缀
|
||||
token-start-with: Bearer
|
||||
# token 过期时间 6个小时
|
||||
expiration: 210000000
|
||||
# 必须使用最少88位的Base64对该令牌进行编码
|
||||
base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI=
|
||||
# 令牌过期时间 此处单位/毫秒 ,默认4小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html
|
||||
token-validity-in-seconds: 14400000
|
||||
# 在线用户key
|
||||
online-key: online-token
|
||||
auth:
|
||||
# 授权路径
|
||||
path: /login
|
||||
# 获取用户信息
|
||||
account: /info
|
||||
online-key: m-online-token
|
||||
|
||||
|
||||
|
||||
#是否开启 swagger-ui
|
||||
|
@ -55,18 +55,15 @@ spring:
|
||||
#jwt
|
||||
jwt:
|
||||
header: Authorization
|
||||
secret: JBqNQX7HD9xhwHP7YSHOP
|
||||
# 令牌前缀
|
||||
token-start-with: Bearer
|
||||
# token 过期时间 2个小时
|
||||
expiration: 7200000
|
||||
# 必须使用最少88位的Base64对该令牌进行编码
|
||||
base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI=
|
||||
# 令牌过期时间 此处单位/毫秒 ,默认2小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html
|
||||
token-validity-in-seconds: 7200000
|
||||
# 在线用户key
|
||||
online-key: online-token
|
||||
auth:
|
||||
# 授权路径
|
||||
path: /login
|
||||
# 获取用户信息
|
||||
account: /info
|
||||
online-key: m-online-token
|
||||
|
||||
|
||||
#是否允许生成代码,生产环境设置为false
|
||||
generator:
|
||||
|
Reference in New Issue
Block a user