Commit 07de0da1 authored by tangtuo's avatar tangtuo

修改鉴权规则

parent 0577d0f2
package com.fzm.admin.auth;
import cn.dev33.satoken.action.SaTokenActionDefaultImpl;
import com.fzm.common.entity.Admin;
import com.fzm.common.entity.User;
import com.fzm.common.service.AdminService;
import com.fzm.common.service.UserService;
import com.fzm.common.utils.JwtUtil;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 继承Sa-Token行为Bean默认实现, 重写部分逻辑
*/
@Component
public class MySaTokenAction extends SaTokenActionDefaultImpl {
@Resource
private AdminService adminService;
/**
* 生成自定义token
*
* @param loginId
* @param loginType
* @return
*/
@Override
public String createToken(Object loginId, String loginType) {
Admin loginUser = adminService.getById((Integer) loginId);
return JwtUtil.generateToken(loginUser);
}
}
package com.fzm.admin.auth;
import cn.dev33.satoken.stp.StpInterface;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author tangtuo
* @date 2021/7/5 15:11
*
* <p>
* 查询当前角色的权限
* </p>
*/
@Component
public class StpServiceImpl implements StpInterface {
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
return null;
}
@Override
public List<String> getRoleList(Object loginId, String loginType) {
return null;
}
}
package com.fzm.admin.controller;
import com.fzm.common.utils.StpAdminUtil;
import com.fzm.common.constant.RedisConstant;
import com.fzm.common.utils.JwtUtil;
import com.fzm.common.utils.RedisUtil;
import com.fzm.admin.params.LoginParam;
import com.fzm.common.constant.TokenConstant;
import com.fzm.common.entity.Admin;
......@@ -14,6 +16,7 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @author tangtuo
......@@ -27,14 +30,18 @@ public class AdminController {
@Resource
private AdminService adminService;
@Resource
private RedisUtil redisUtil;
@PostMapping("/login")
@ApiOperation(value = "登录")
public ResponseModel<Map<String, Object>> login(@Validated @RequestBody LoginParam loginParam) {
Admin admin = adminService.login(loginParam.getUsername(), loginParam.getPassword());
StpAdminUtil.login(admin.getId());
String token = JwtUtil.generateToken(admin);
redisUtil.setEx(RedisConstant.ADMIN_USER_TOKEN_PREFIX + admin.getId(), token, 2L, TimeUnit.HOURS);
HashMap<String, Object> result = new HashMap<>();
result.put("user", admin);
result.put(TokenConstant.TOKEN_HEADER, StpAdminUtil.getTokenValue());
result.put(TokenConstant.TOKEN_HEADER, token);
return ResponseModel.success(result);
}
}
package com.fzm.admin.controller;
import cn.dev33.satoken.annotation.SaCheckLogin;
import com.fzm.common.utils.StpAdminUtil;
import com.fzm.common.annotation.Authentication;
import com.fzm.common.entity.Category;
import com.fzm.common.model.ResponseModel;
import com.fzm.common.service.CategoryService;
......@@ -18,7 +17,7 @@ import java.util.List;
* @author tangtuo
* @date 2021/7/1 14:37
*/
@SaCheckLogin(type = StpAdminUtil.TYPE)
@Authentication
@RestController
@RequestMapping(value = "/category")
@Api(tags = "类目管理")
......
package com.fzm.admin.controller;
import cn.dev33.satoken.annotation.SaCheckLogin;
import com.fzm.common.utils.StpAdminUtil;
import com.fzm.common.annotation.Authentication;
import com.fzm.common.entity.Label;
import com.fzm.common.model.ResponseModel;
import com.fzm.common.service.LabelService;
......@@ -18,7 +17,7 @@ import java.util.List;
* @author tangtuo
* @date 2021/7/1 14:37
*/
@SaCheckLogin(type = StpAdminUtil.TYPE)
@Authentication
@RestController
@RequestMapping(value = "/label")
@Api(tags = "标签管理")
......
package com.fzm.admin.controller;
import cn.dev33.satoken.annotation.SaCheckLogin;
import com.fzm.common.utils.StpAdminUtil;
import com.fzm.common.annotation.Authentication;
import com.fzm.common.entity.Nft;
import com.fzm.common.entity.vo.NftListVo;
import com.fzm.common.model.ResponseModel;
......@@ -18,7 +17,7 @@ import javax.annotation.Resource;
* @author tangtuo
* @date 2021/7/5 15:34
*/
@SaCheckLogin(type = StpAdminUtil.TYPE)
@Authentication
@RestController
@RequestMapping("/nft")
@Api(tags = "剧本nft管理")
......
package com.fzm.admin.controller;
import cn.dev33.satoken.annotation.SaCheckLogin;
import com.fzm.common.utils.StpAdminUtil;
import com.fzm.common.annotation.Authentication;
import com.fzm.common.entity.vo.UserListVo;
import com.fzm.common.entity.vo.UserStatisticVo;
import com.fzm.common.model.ResponseModel;
......@@ -23,7 +22,7 @@ import java.util.List;
* @author tangtuo
* @date 2021/7/5 10:01
*/
@SaCheckLogin(type = StpAdminUtil.TYPE)
@Authentication
@RestController
@RequestMapping("/admin")
@Api(tags = "用户管理")
......
......@@ -54,22 +54,6 @@ spring:
redis:
# 缓存失效时间
time-to-live: 86400000
# sa-token配置
sa-token:
# token名称 (同时也是cookie名称)
token-name: Authorization
# token有效期,单位s, -1代表永不过期
timeout: 7200
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: false
# token风格
#token-style: uuid
# 是否输出操作日志
is-log: false
tokenPrefix: Bearer
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: false
swagger:
title: 乐映影视后台管理系统
description: 乐映影视后台管理系统RESTFUL API
......
......@@ -54,21 +54,6 @@ spring:
redis:
# 缓存失效时间
time-to-live: 86400000
# sa-token配置
sa-token:
# token名称 (同时也是cookie名称)
token-name: Authorization
# token有效期,单位s 默认30天, -1代表永不过期
timeout: 7200
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: false
# token风格
#token-style: uuid
# 是否输出操作日志
is-log: false
tokenPrefix: Bearer
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: false
swagger:
title: 乐映影视乐映影视后台管理系统
......
......@@ -54,22 +54,6 @@ spring:
redis:
# 缓存失效时间
time-to-live: 86400000
# sa-token配置
sa-token:
# token名称 (同时也是cookie名称)
token-name: Authorization
# token有效期,单位s, -1代表永不过期
timeout: 7200
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: false
# token风格
#token-style: uuid
# 是否输出操作日志
is-log: false
tokenPrefix: Bearer
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: false
swagger:
title: 乐映影视乐映影视后台管理系统
description: 乐映影视后台管理系统RESTFUL API
......
......@@ -53,16 +53,6 @@
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
<!-- Sa-Token 权限认证, 在线文档:http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
</dependency>
<!-- Sa-Token整合redis (使用jackson序列化方式) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis-jackson</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
......
package com.fzm.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author tangtuo
* @date 2021/7/13 14:23
*/
@Target(value = {ElementType.METHOD, ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Authentication {
String[] permissions() default {};
}
package com.fzm.common.config;
import cn.dev33.satoken.interceptor.SaAnnotationInterceptor;
import com.fzm.common.interceptor.AuthenticationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
// 注册Sa-Token的注解拦截器,打开注解式鉴权功能
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册注解拦截器,并排除不需要注解鉴权的接口地址 (与登录拦截器无关)
registry.addInterceptor(new SaAnnotationInterceptor()).addPathPatterns("/**");
registry.addInterceptor(authenticationInterceptor())
.addPathPatterns("/**"); // 拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要登录
}
@Bean
public AuthenticationInterceptor authenticationInterceptor() {
return new AuthenticationInterceptor();
}
}
......@@ -11,9 +11,15 @@ public class RedisConstant {
*/
public static final String COLLECTION_USER_PREFIX = "collection:user:";
/**
* 门户用户token前缀
*/
public static final String PORTAL_USER_TOKEN_PREFIX = "portal:user:token:";
/**
* 后台管理用户token前缀
*/
public static final String ADMIN_USER_TOKEN_PREFIX = "admin:user:token:";
}
package com.fzm.common.exception.handler;
import cn.dev33.satoken.exception.*;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpStatus;
import com.fzm.common.constant.TokenConstant;
import com.fzm.common.enums.ResultCode;
import com.fzm.common.exception.GlobalException;
import com.fzm.common.model.ResponseModel;
import com.fzm.common.utils.JwtUtil;
import com.fzm.common.utils.StpAdminUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.ObjectError;
......@@ -20,7 +13,6 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
......@@ -50,37 +42,6 @@ public class GlobalExceptionHandler {
return ResponseModel.fail(exception);
}
@ExceptionHandler(value = SaTokenException.class)
public ResponseModel<String> handlerNotLoginException(SaTokenException exception) {
log.error(exception.getMessage(), exception);
if (exception instanceof NotLoginException) {
if (exception.getMessage().contains("token已被顶下线")) {
// 获取已过期的token
String expireToken = request.getHeader(TokenConstant.TOKEN_HEADER);
String appId = JwtUtil.getAppIdFromToken(expireToken);
// 从已过期的token中获取用户id
Integer userId = JwtUtil.getUserIdFromToken(expireToken);
String tokenValue;
if (TokenConstant.TOKEN_APP_ID_PORTAL.equals(appId)) {
tokenValue = StpUtil.getTokenValueByLoginId(userId);
} else {
tokenValue = StpAdminUtil.getTokenValueByLoginId(userId);
}
Date createTime = JwtUtil.getCreateTimeFromToken(tokenValue);
// 获取最新的token
String format = DateUtil.format(createTime, "yyyy-MM-dd HH:mm:ss");
return ResponseModel.fail(ResultCode.UNAUTHORIZED,
String.format("您的账号于 %s 登录另外一台设备,如非您本人所为,请立即修改密码", format));
} else {
return ResponseModel.fail(ResultCode.UNAUTHORIZED, exception.getMessage());
}
} else if (exception instanceof NotPermissionException || exception instanceof NotRoleException || exception instanceof StopMatchException) {
return ResponseModel.fail(ResultCode.FORBIDDEN, ResultCode.FORBIDDEN.getMessage());
} else {
return ResponseModel.fail(exception);
}
}
@ExceptionHandler(value = {MethodArgumentNotValidException.class})
public ResponseModel<String> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
......
package com.fzm.common.interceptor;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
import com.fzm.common.annotation.Authentication;
import com.fzm.common.constant.RedisConstant;
import com.fzm.common.constant.TokenConstant;
import com.fzm.common.entity.AbstractUser;
import com.fzm.common.enums.ResultCode;
import com.fzm.common.exception.GlobalException;
import com.fzm.common.service.AdminService;
import com.fzm.common.service.UserService;
import com.fzm.common.utils.JwtUtil;
import com.fzm.common.utils.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Date;
/**
* @author tangtuo
* @date 2021/7/13 14:30
*/
public class AuthenticationInterceptor implements HandlerInterceptor {
@Resource
private RedisUtil redisUtil;
@Resource
private UserService userService;
@Resource
private AdminService adminService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 如果不是映射到方法直接通过
if (!(handler instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
Class<?> cls = method.getDeclaringClass();
// 先判断目标方法所在的类是否加了Authentication注解,再判断目标方法是否加了Authentication注解
if (cls.isAnnotationPresent(Authentication.class) || method.isAnnotationPresent(Authentication.class)) {
String token = request.getHeader("Authorization");
if (StringUtils.isBlank(token)) {
throw GlobalException.newException(ResultCode.UNAUTHORIZED, "请先登录");
}
if (!token.startsWith(TokenConstant.TOKEN_PREFIX)) {
throw GlobalException.newException(ResultCode.UNAUTHORIZED, "非法token");
}
if (JwtUtil.isTokenExpired(token)) {
throw GlobalException.newException(ResultCode.UNAUTHORIZED, "登录已过期");
}
String realToken = token.substring(TokenConstant.TOKEN_PREFIX.length());
String appId = JwtUtil.getAppIdFromToken(token);
Integer userId = JwtUtil.getUserIdFromToken(token);
AbstractUser user;
String redisToken;
if (TokenConstant.TOKEN_APP_ID_PORTAL.equals(appId)) {
// 门户用户
user = userService.getById(userId);
redisToken = redisUtil.get(RedisConstant.PORTAL_USER_TOKEN_PREFIX + userId);
} else {
// 后台管理用户
user = adminService.getById(userId);
redisToken = redisUtil.get(RedisConstant.ADMIN_USER_TOKEN_PREFIX + userId);
}
if (user == null) {
throw GlobalException.newException(ResultCode.UNAUTHORIZED, "非法用户请求");
}
if (StringUtils.isBlank(redisToken)) {
throw GlobalException.newException(ResultCode.UNAUTHORIZED, "登录已过期");
}
if (!redisToken.equals(realToken)) {
Date date = JwtUtil.getCreateTimeFromToken(realToken);
String format = DateUtil.format(date, "yyyy-MM-dd HH:mm:ss");
throw GlobalException.newException(ResultCode.UNAUTHORIZED,
String.format("您的账号于 %s 登录另外一台设备,如非您本人所为,请立即修改密码", format));
}
// todo 认证完毕,对后台用户进行鉴权
/*if (TokenConstant.TOKEN_APP_ID_ADMIN.equals(appId)) {
Authentication annotation = method.getAnnotation(Authentication.class);
String[] permissions = annotation.permissions();
if (ArrayUtil.isNotEmpty(permissions)) {
}
}*/
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
public static void main(String[] args) {
String token = "Bearer token121323433 ";
System.out.println(token.substring("Bearer ".length()));
}
}
package com.fzm.common.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import cn.fzm.chain.simplesdk.client.ParaChainClient;
import cn.fzm.chain.simplesdk.constant.TxStatusEnum;
import cn.fzm.chain.simplesdk.model.TxResult;
......@@ -13,7 +12,6 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fzm.common.constant.RedisConstant;
import com.fzm.common.constant.SystemConstant;
import com.fzm.common.entity.*;
import com.fzm.common.entity.TbCollection;
import com.fzm.common.entity.vo.CollectionNftVo;
import com.fzm.common.entity.vo.NftListVo;
import com.fzm.common.enums.ResultCode;
......@@ -24,6 +22,7 @@ import com.fzm.common.service.CollectionService;
import com.fzm.common.service.NftService;
import com.fzm.common.service.UserService;
import com.fzm.common.utils.JsonUtil;
import com.fzm.common.utils.JwtUtil;
import com.fzm.common.utils.OssUtil;
import com.fzm.common.utils.RedisUtil;
import com.github.pagehelper.PageHelper;
......@@ -36,6 +35,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;
......@@ -69,12 +69,15 @@ public class NftServiceImpl extends ServiceImpl<NftMapper, Nft> implements NftSe
@Resource
private OssUtil ossUtil;
@Resource
private HttpServletRequest request;
@Value("${chain.para.contract-name}")
private String contractName;
@Override
public NftDto saveNft(Nft nft) {
User user = userService.getById(StpUtil.getLoginIdAsInt());
User user = userService.getById(JwtUtil.getUserIdFromToken(request.getHeader("Authorization")));
save(nft);
NftDto nftDto = new NftDto();
// 获取用户的钱包地址
......@@ -88,7 +91,7 @@ public class NftServiceImpl extends ServiceImpl<NftMapper, Nft> implements NftSe
@Override
public Boolean publish(NftDto nftDto) {
User user = userService.getById(StpUtil.getLoginIdAsInt());
User user = userService.getById(JwtUtil.getUserIdFromToken(request.getHeader("Authorization")));
String wallet = user.getWallet();
// 获取用户的私钥
String privkey = paraChainClient.walletDumpPrivkey(wallet);
......@@ -154,7 +157,7 @@ public class NftServiceImpl extends ServiceImpl<NftMapper, Nft> implements NftSe
@Override
public Boolean collection(Integer id) {
int userId = StpUtil.getLoginIdAsInt();
int userId = JwtUtil.getUserIdFromToken(request.getHeader("Authorization"));
String key = RedisConstant.COLLECTION_USER_PREFIX + userId;
// 如果用户收藏的nft已经存在列表里,那么就是取消收藏
if (redisUtil.sIsMember(key, id.toString())) {
......@@ -174,9 +177,9 @@ public class NftServiceImpl extends ServiceImpl<NftMapper, Nft> implements NftSe
@Override
public List<CollectionNftVo> getCollectionList() {
int userId = StpUtil.getLoginIdAsInt();
int userId = JwtUtil.getUserIdFromToken(request.getHeader("Authorization"));
// 从redis里获取当前用户的收藏列表
Set<String> set = redisUtil.setMembers(RedisConstant.COLLECTION_USER_PREFIX + StpUtil.getLoginIdAsInt());
Set<String> set = redisUtil.setMembers(RedisConstant.COLLECTION_USER_PREFIX + userId);
List<Integer> list;
if (CollectionUtil.isEmpty(set)) {
// redis里为空,再从mysql里查一次
......
package com.fzm.common.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import cn.fzm.chain.simplesdk.client.ParaChainClient;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
......@@ -23,18 +21,18 @@ import com.fzm.common.params.LoginParam;
import com.fzm.common.properties.SmsProperties;
import com.fzm.common.service.AuthPersonService;
import com.fzm.common.service.UserService;
import com.fzm.common.utils.JwtUtil;
import com.fzm.common.utils.RedisUtil;
import com.fzm.common.utils.SmsUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author tangtuo
......@@ -65,6 +63,9 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Resource
private ParaChainClient paraClient;
@Resource
private HttpServletRequest request;
@Override
public User loadUserByUsername(String username) {
QueryWrapper<User> wrapper = new QueryWrapper<>();
......@@ -121,11 +122,11 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Override
public User getUserByToken() {
String token = StpUtil.getTokenValue();
String token = request.getHeader("Authorization");
if (StringUtils.isBlank(token)) {
throw GlobalException.newException(ResultCode.UNAUTHORIZED, "您还没有登录,请先登录");
}
Integer userId = StpUtil.getLoginIdAsInt();
Integer userId = JwtUtil.getUserIdFromToken(token);
return getById(userId);
}
......@@ -145,7 +146,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Override
public Boolean personAuth(AuthPerson authPerson) {
Integer loginId = StpUtil.getLoginIdAsInt();
Integer loginId = JwtUtil.getUserIdFromToken(request.getHeader("Authorization"));
User user = new User().
setAuthStatus(AuthStatusEnum.ONGOING.getStatus()).
setAuthType(AuthTypeEnum.PERSON.getType()).
......@@ -157,7 +158,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Override
public User uploadAvatar(String avatar) {
Integer loginId = StpUtil.getLoginIdAsInt();
Integer loginId = JwtUtil.getUserIdFromToken(request.getHeader("Authorization"));
User user = new User().
setAvatar(avatar).
setId(loginId);
......
......@@ -2,6 +2,7 @@ package com.fzm.common.utils;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.fzm.common.constant.TokenConstant;
import com.fzm.common.entity.AbstractUser;
import com.fzm.common.enums.ResultCode;
import com.fzm.common.exception.GlobalException;
......@@ -26,7 +27,8 @@ public class JwtUtil {
private static final String CLAIM_KEY_USERID = "userId";
private static final String CLAIM_KEY_APP_ID = "appId";
private static final String SECRET = "fzm-ly";
private static final Long EXPIRATION = 1000 * 60 * 60 * 24L;
private static final Long PORTAL_EXPIRATION = 1000 * 60 * 60 * 24L;
private static final Long ADMIN_EXPIRATION = 1000 * 60 * 60 * 2L;
private static final String TOKEN_PREFIX = "Bearer ";
/**
......@@ -35,7 +37,7 @@ public class JwtUtil {
private static String generateToken(Map<String, Object> claims) {
return Jwts.builder()
.setClaims(claims)
.setExpiration(generateExpirationDate())
.setExpiration(generateExpirationDate((String) claims.get(CLAIM_KEY_APP_ID)))
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
}
......@@ -60,8 +62,14 @@ public class JwtUtil {
/**
* 生成token的过期时间
*/
private static Date generateExpirationDate() {
return new Date(System.currentTimeMillis() + EXPIRATION * 1000);
private static Date generateExpirationDate(String appId) {
long expiration;
if (TokenConstant.TOKEN_APP_ID_PORTAL.equals(appId)) {
expiration = PORTAL_EXPIRATION;
} else {
expiration = ADMIN_EXPIRATION;
}
return new Date(System.currentTimeMillis() + expiration);
}
/**
......@@ -114,7 +122,7 @@ public class JwtUtil {
/**
* 判断token是否已经失效
*/
private static boolean isTokenExpired(String token) {
public static boolean isTokenExpired(String token) {
Date expiredDate = getExpiredDateFromToken(token);
return expiredDate.before(new Date());
}
......@@ -127,6 +135,7 @@ public class JwtUtil {
return claims.getExpiration();
}
/**
* 根据用户信息生成token
*/
......
package com.fzm.portal.auth;
import com.fzm.common.entity.User;
import com.fzm.common.service.UserService;
import com.fzm.common.utils.JwtUtil;
import org.springframework.stereotype.Component;
import cn.dev33.satoken.action.SaTokenActionDefaultImpl;
import javax.annotation.Resource;
/**
* 继承Sa-Token行为Bean默认实现, 重写部分逻辑
*/
@Component
public class MySaTokenAction extends SaTokenActionDefaultImpl {
@Resource
private UserService userService;
/**
* 生成自定义token
*
* @param loginId
* @param loginType
* @return
*/
@Override
public String createToken(Object loginId, String loginType) {
User loginUser = userService.getById((Integer)loginId);
return JwtUtil.generateToken(loginUser);
}
}
package com.fzm.portal.auth;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Component;
import cn.dev33.satoken.stp.StpInterface;
/**
* 自定义权限验证接口扩展
*/
@Component
public class StpInterfaceImpl implements StpInterface {
/**
* 返回一个账号所拥有的权限码集合
*/
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
return null;
}
/**
* 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)
*/
@Override
public List<String> getRoleList(Object loginId, String loginType) {
return null;
}
}
package com.fzm.portal.controller;
import cn.dev33.satoken.annotation.SaCheckLogin;
import com.fzm.common.annotation.Authentication;
import com.fzm.common.entity.vo.CollectionNftVo;
import com.fzm.common.model.ResponseModel;
import com.fzm.common.service.NftService;
......@@ -10,9 +10,7 @@ import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author tangtuo
......@@ -26,7 +24,7 @@ public class CollectionController {
@Resource
private NftService nftService;
@SaCheckLogin
@Authentication
@PostMapping("/add")
@ApiOperation(value = "收藏 | 取消收藏", notes = "用户如果已经收藏了当前作品的话就是取消收藏,反之就是收藏")
public ResponseModel add(@ApiParam(value = "nft的主键") @RequestParam Integer id) {
......@@ -34,10 +32,10 @@ public class CollectionController {
return ResponseModel.success(result);
}
@SaCheckLogin
@Authentication
@GetMapping("/list")
@ApiOperation(value = "获取用户的收藏列表")
private ResponseModel<List<CollectionNftVo>> list() {
private ResponseModel<List<CollectionNftVo>> list(@RequestHeader(value = "Authorization") String token) {
List<CollectionNftVo> list = nftService.getCollectionList();
return ResponseModel.success(list);
}
......
package com.fzm.portal.controller;
import com.fzm.common.entity.Category;
import com.fzm.common.entity.Label;
import com.fzm.common.model.ResponseModel;
import com.fzm.common.service.CategoryService;
import com.fzm.common.service.LabelService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
......
package com.fzm.portal.controller;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.crypto.SecureUtil;
import com.fzm.common.annotation.Authentication;
import com.fzm.common.constant.SystemConstant;
import com.fzm.common.entity.Nft;
import com.fzm.common.entity.NftDto;
......@@ -16,6 +15,7 @@ import com.fzm.common.model.ResponseModel;
import com.fzm.common.service.CategoryService;
import com.fzm.common.service.NftService;
import com.fzm.common.service.UserService;
import com.fzm.common.utils.JwtUtil;
import com.fzm.common.utils.OssUtil;
import com.fzm.common.utils.QRCodeUtil;
import io.swagger.annotations.Api;
......@@ -27,6 +27,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
......@@ -55,6 +56,9 @@ public class NftController {
@Resource
private CategoryService categoryService;
@Resource
private HttpServletRequest request;
/**
* 存证二维码跳转地址
* todo 修改成动态前端路由
......@@ -62,7 +66,7 @@ public class NftController {
private static final String PATH = "https://chain.33.cn/document/60";
@SaCheckLogin
@Authentication
@PostMapping("/save")
@ApiOperation(value = "nft基本信息保存(基本信息和加密上链两个步骤)")
public ResponseModel<NftDto> save(@ApiParam(value = "类目id", required = true) Integer categoryId,
......@@ -92,7 +96,7 @@ public class NftController {
nft.setFileUrl(fileUrl).setIsGrant(isGrant).setFileName(file.getOriginalFilename());
}
nft.setCategoryId(categoryId)
.setUserId(StpUtil.getLoginIdAsInt())
.setUserId(JwtUtil.getUserIdFromToken(request.getHeader("Authorization")))
.setName(name)
.setAuthor(author)
.setTheme(theme)
......@@ -103,7 +107,7 @@ public class NftController {
}
@SaCheckLogin
@Authentication
@PostMapping("/publish")
@ApiOperation("发行nft")
public ResponseModel<Boolean> publish(@Validated @RequestBody NftDto nftDto) {
......@@ -138,11 +142,11 @@ public class NftController {
return ResponseModel.success(nftVo);
}
@SaCheckLogin
@Authentication
@GetMapping("/list/current")
@ApiOperation(value = "获取我的nft列表")
public ResponseModel<Map<String, Object>> listCurrent(@ApiParam(value = "类目id,查询全部的时候传null") @RequestParam(required = false) Integer categoryId) {
List<Nft> list = nftService.listCurrent(categoryId, StpUtil.getLoginIdAsInt());
List<Nft> list = nftService.listCurrent(categoryId, JwtUtil.getUserIdFromToken(request.getHeader("Authorization")));
List<CollectionNftVo> nftVoList = list.stream()
.map(nft -> new CollectionNftVo(nft, categoryService.getCategoryById(nft.getCategoryId())))
.collect(Collectors.toList());
......@@ -152,7 +156,7 @@ public class NftController {
return ResponseModel.success(result);
}
@SaCheckLogin
@Authentication
@GetMapping("/generateNftId")
@ApiOperation(value = "生成nft编号")
public ResponseModel<String> generateNftId(@ApiParam(value = "类目id", required = true) @RequestParam Integer categoryId) {
......@@ -160,7 +164,7 @@ public class NftController {
return ResponseModel.success(nftId);
}
@SaCheckLogin
@Authentication
@PostMapping("/file/md5")
@ApiOperation(value = "获取文件的md5值")
public ResponseModel<String> getFileMd5Value(MultipartFile file) throws IOException {
......@@ -169,15 +173,15 @@ public class NftController {
}
@SaCheckLogin
@Authentication
@GetMapping("/certificate/{id}")
@ApiOperation(value = "nft证书")
public ResponseModel<NftCertificateVo> certificate(@PathVariable Integer id) throws Exception {
public ResponseModel<NftCertificateVo> certificate(@PathVariable Integer id, @RequestHeader String Authorization) throws Exception {
Nft nft = nftService.getById(id);
if (nft == null) {
throw GlobalException.newException(ResultCode.DATA_ERROR, "没找到此nft的详情");
}
int userId = StpUtil.getLoginIdAsInt();
int userId = JwtUtil.getUserIdFromToken(Authorization);
if (!nft.getUserId().equals(userId)) {
throw GlobalException.newException(ResultCode.FORBIDDEN, "您无权查看别人的nft证书");
}
......
package com.fzm.portal.controller;
import cn.dev33.satoken.annotation.SaCheckLogin;
import com.fzm.common.annotation.Authentication;
import com.fzm.common.model.ResponseModel;
import com.fzm.common.utils.OssUtil;
import io.swagger.annotations.Api;
......@@ -24,7 +24,7 @@ public class OssController {
@Resource
private OssUtil ossUtil;
@SaCheckLogin
@Authentication
@GetMapping("/policy")
@ApiOperation("完成oss签名")
public ResponseModel<Map<String, String>> policy() {
......
package com.fzm.portal.controller;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.stp.StpUtil;
import com.fzm.common.annotation.Authentication;
import com.fzm.common.constant.RedisConstant;
import com.fzm.common.constant.TokenConstant;
import com.fzm.common.entity.AuthPerson;
import com.fzm.common.entity.User;
......@@ -10,7 +10,9 @@ import com.fzm.common.exception.GlobalException;
import com.fzm.common.model.ResponseModel;
import com.fzm.common.params.LoginParam;
import com.fzm.common.service.UserService;
import com.fzm.common.utils.JwtUtil;
import com.fzm.common.utils.OssUtil;
import com.fzm.common.utils.RedisUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
......@@ -22,6 +24,7 @@ import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @author tangtuo
......@@ -38,6 +41,9 @@ public class UserController {
@Resource
private OssUtil ossUtil;
@Resource
private RedisUtil redisUtil;
@PostMapping(value = "/login")
@ApiOperation(value = "登录|注册")
public ResponseModel<Map<String, Object>> login(@RequestBody @Validated LoginParam param) {
......@@ -54,10 +60,11 @@ public class UserController {
throw GlobalException.newException(ResultCode.VALIDATE_FAILED, "密码和验证码只能一个为空");
}
User user = userService.login(param);
StpUtil.login(user.getId());
String token = JwtUtil.generateToken(user);
redisUtil.setEx(RedisConstant.PORTAL_USER_TOKEN_PREFIX + user.getId(), token, 24L, TimeUnit.HOURS);
HashMap<String, Object> result = new HashMap<>();
result.put("user", user);
result.put(TokenConstant.TOKEN_HEADER, StpUtil.getTokenValue());
result.put(TokenConstant.TOKEN_HEADER, token);
return ResponseModel.success(result);
}
......@@ -79,17 +86,17 @@ public class UserController {
return ResponseModel.success();
}
@SaCheckLogin
@Authentication
@ApiOperation(value = "修改昵称 | 修改个性签名", notes = "用户修改哪项信息就传那一个参数就可以了")
@PostMapping("/update")
public ResponseModel<User> update(@Validated @RequestBody User user) {
Integer userId = StpUtil.getLoginIdAsInt();
public ResponseModel<User> update(@Validated @RequestBody User user, @RequestHeader String Authorization) {
Integer userId = JwtUtil.getUserIdFromToken(Authorization);
user.setId(userId);
userService.updateById(user);
return ResponseModel.success(userService.getById(userId));
}
@SaCheckLogin
@Authentication
@ApiOperation(value = "上传头像")
@PostMapping("/upload/avatar")
public ResponseModel<User> uploadAvatar(MultipartFile file) throws IOException {
......@@ -98,7 +105,7 @@ public class UserController {
return ResponseModel.success(user);
}
@SaCheckLogin
@Authentication
@GetMapping("/detail")
@ApiOperation(value = "获取用户详情")
public ResponseModel<User> getUserDetail() {
......@@ -106,7 +113,7 @@ public class UserController {
}
@SaCheckLogin
@Authentication
@PostMapping("/auth/person")
@ApiOperation(value = "个人认证")
public ResponseModel<Boolean> personAuth(@RequestBody @Validated AuthPerson authPerson) {
......@@ -114,7 +121,7 @@ public class UserController {
}
@SaCheckLogin
@Authentication
@PostMapping("/auth/enterprise")
@ApiOperation(value = "企业认证")
public ResponseModel<Boolean> enterpriseAuth() {
......
......@@ -60,21 +60,6 @@ spring:
simple:
####开启手动签收
acknowledge-mode: manual
# sa-token配置
sa-token:
# token名称 (同时也是cookie名称)
token-name: Authorization
# token有效期,单位s 默认30天, -1代表永不过期
timeout: 86400
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: false
# token风格
#token-style: uuid
# 是否输出操作日志
is-log: true
tokenPrefix: Bearer
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: false
swagger:
title: 乐映影视门户系统
......
......@@ -60,21 +60,6 @@ spring:
simple:
####开启手动签收
acknowledge-mode: manual
# sa-token配置
sa-token:
# token名称 (同时也是cookie名称)
token-name: Authorization
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
timeout: 86400
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: false
# token风格
#token-style: uuid
# 是否输出操作日志
is-log: true
tokenPrefix: Bearer
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: false
swagger:
title: 乐映影视门户系统
......
......@@ -60,21 +60,6 @@ spring:
simple:
####开启手动签收
acknowledge-mode: manual
# sa-token配置
sa-token:
# token名称 (同时也是cookie名称)
token-name: Authorization
# token有效期,单位s 默认30天, -1代表永不过期
timeout: 86400
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: false
# token风格
#token-style: uuid
# 是否输出操作日志
is-log: true
tokenPrefix: Bearer
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: false
swagger:
title: 乐映影视门户系统
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment