1.登录获取用户信息并写入token
@Overridepublic CommonResult loginV2(RcSysUserEntity byAccount) {log.info("********************");log.info("******************** account-V2:{}",byAccount.getAccount());log.info("********************");CommonResult userInfoV2 = getUserInfoV2(byAccount);return userInfoV2;}//todopublic CommonResult getUserInfoV2(RcSysUserEntity byAccount){List<TMenu> menus= new ArrayList<>();String tokenResult="";Map<String, Object> result = new HashMap<>();try {//获取权限信息Optional<TRole> tRoleopt=tRoleRepository.findById(Integer.valueOf(byAccount.getRoleId()));if(tRoleopt.isPresent()){TRole role = tRoleopt.get();List<TMenu> tMenus = tRoleService.querySysMenus(role.getMenuIds());menus = tRoleService.buildMenuTreeSelect(tMenus);}if(null!=byAccount){JwtPayLoad jwtPayLoad = new JwtPayLoad();jwtPayLoad.setId(byAccount.getId());
// jwtPayLoad.setToken(byAccount.getToken());jwtPayLoad.setAccount(byAccount.getAccount());jwtPayLoad.setRealname(byAccount.getRealname());jwtPayLoad.setRoleId(byAccount.getRoleId());jwtPayLoad.setCtime(byAccount.getCtime());jwtPayLoad.setCuser(byAccount.getCuser());jwtPayLoad.setTel(byAccount.getTel());jwtPayLoad.setEmail(byAccount.getEmail());tokenResult = JwtTokenUtil.createToken(jwtPayLoad);result.put("token", tokenResult);result.put("permission", menus);result.put("userInfo", byAccount);//更新登录tokenbyAccount.setToken(tokenResult);rcSysUserRepository.save(byAccount);//写入登录日志AsyncManager.me().execute(AsyncFactory.recordLogininfor(byAccount.getAccount(), byAccount.getAccount(), String.valueOf(byAccount.getId()), String.valueOf(byAccount.getId()), "", Constants.LOGIN_SUCCESS, "登录成功"));return CommonResult.success(result);}} catch (Exception e) {logger.info(e.getMessage());}return CommonResult.failed("认证失败,用户名或密码错误");}
2.token验证获取用户信息
/*** token验证获取用户信息* @param token* @return*/@ApiOperation(value = "token验证获取用户信息",httpMethod = "POST")@RequestMapping(value = "tokenAuth")@ResponseBodypublic CommonResult tokenAuth(String token) {RcSysUserEntity userInfo = null;try {logger.debug("token验证获取用户信息...");RcSysUserEntity byToken = rcSysUserRepository.findByToken(token);if (null==byToken) return CommonResult.failed("token验证获取用户信息失效!");JwtPayLoad jwtPayLoad = JwtTokenUtil.getJwtPayLoad(token);CommonResult tokenUser = loginService.getTokenUserV2(jwtPayLoad);logger.debug("userInfo:{}",JSONObject.toJSONString(tokenUser.getData()));logger.debug("token验证获取用户信息 success !");return tokenUser;} catch (Exception e) {logger.debug("token验证获取用户信息 error !");e.printStackTrace();}Map<String, Object> resultMap=new HashMap<>();resultMap.put("userInfo",userInfo);logger.debug("resultMap:{}",JSONObject.toJSONString(resultMap));return CommonResult.success(resultMap);}
public CommonResult getTokenUserV2(JwtPayLoad jwtPayLoad) {Long id=jwtPayLoad.getId();Optional<RcSysUserEntity> byAccountOpt = rcSysUserRepository.findById(id);if (byAccountOpt.isPresent()) {RcSysUserEntity byAccount = byAccountOpt.get();//移除加密信息byAccount.setSalt("");byAccount.setPassword("");Optional<TRole> tRoleopt=tRoleRepository.findById(Integer.valueOf(byAccount.getRoleId()));if(tRoleopt.isPresent()){TRole role = tRoleopt.get();List<TMenu> tMenus = tRoleService.querySysMenus(role.getMenuIds());List<TMenu> menus = tRoleService.buildMenuTreeSelect(tMenus);byAccount.setMenus(menus);return CommonResult.success(byAccount);}}return CommonResult.failed("token验证获取用户信息失败!");}@Overridepublic List<TMenu> querySysMenus(String menu) {RowMapper<TMenu> rowMapper=new BeanPropertyRowMapper<>(TMenu.class);String query=" select * from t_sys_menu where 1=1 ";if (!menu.equals("-1")) {//-1为查全部query+=" and find_in_set(id,'"+menu+"') ";}List<TMenu> list = jdbcTemplate.query(query,rowMapper);return list;}/*** 构建前端所需要下拉树结构** @param menus 菜单列表* @return 下拉树结构列表*/@Overridepublic List<TMenu> buildMenuTreeSelect(List<TMenu> menus){//转换为前端data格式List<TMenu> topNodes=menus.stream().filter(item->item.getParentId()==0).collect(Collectors.toList());List<TMenu> nodes=new ArrayList<>();for(TMenu item : topNodes){TMenu combotreeVo = new TMenu();combotreeVo.setId(item.getId());combotreeVo.setMenuName(item.getMenuName());combotreeVo.setParentId(item.getParentId());combotreeVo.setMenuUrl(item.getMenuUrl());fillSubNode(combotreeVo,menus);if(combotreeVo.getChildren()!=null&&combotreeVo.getChildren().size()>0){combotreeVo.setStatus(0);}else{combotreeVo.setStatus(1);}nodes.add(combotreeVo);}return nodes;}/*** 转换* @param pnode* @param all*/public void fillSubNode(TMenu pnode, List<TMenu> all) {List<TMenu> subNodes = all.stream().filter(item -> item.getParentId()==pnode.getId()).collect(Collectors.toList());if (subNodes == null || subNodes.size() == 0) {return;}pnode.setChildren(new ArrayList<TMenu>());for (TMenu item : subNodes) {TMenu combotreeVo = new TMenu();combotreeVo.setId(item.getId());combotreeVo.setMenuName(item.getMenuName());combotreeVo.setParentId(item.getParentId());combotreeVo.setMenuUrl(item.getMenuUrl());fillSubNode(combotreeVo, all);if (combotreeVo.getChildren() != null && combotreeVo.getChildren().size() > 0) {combotreeVo.setStatus(0);} else {combotreeVo.setStatus(1);}pnode.getChildren().add(combotreeVo);}}
3.退出
@ApiOperation(value = "退出", httpMethod = "POST")@RequestMapping(value = "/logout")@ResponseBodypublic CommonResult logout(@RequestParam(value = "token", required = true) String token) {RcSysUserEntity byToken = rcSysUserRepository.findByToken(token);if (byToken == null) return CommonResult.failed("token参数异常!");byToken.setToken("");rcSysUserRepository.save(byToken);return CommonResult.success("退出成功!");}
4.角色和权限实体类
package com.zkdj.data.entity.pojo;import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;import javax.persistence.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;/*** @description 系统角色权限表* @author gxf* @date 2023-06-02*/
@Entity
@Data
@Table(name="t_sys_menu")
@ApiModel("系统角色权限表")
public class TMenu implements Serializable {private static final long serialVersionUID = 1L;/*** 主键*/@Id@ApiModelProperty("主键")@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "id", nullable = false)private Integer id;/*** 菜单名称*/@ApiModelProperty("菜单名称")@Column(name="menu_name")private String menuName;/*** 父级id*/@ApiModelProperty("父级id")@Column(name="parent_id")private Integer parentId;/*** 菜单路径*/@ApiModelProperty("菜单路径")@Column(name="menu_url")private String menuUrl;/*** 创建时间*/@ApiModelProperty("创建时间")@Column(name="ctime")private String ctime;/*** 修改时间*/@ApiModelProperty("修改时间")@Column(name="utime")private String utime;/*** 状态 : 0 未启用 1 已启用*/@ApiModelProperty("状态 : 0 未启用 1 已启用")@Column(name="status")private Integer status;/*** 排序*/@ApiModelProperty("排序")@Column(name="sort")private Integer sort;/*** 是否是父级 0 不是 1是*/@ApiModelProperty("是否是父级 0 不是 1是")@Column(name="is_parent")private Integer isParent;/** 子节点 */@JsonInclude(JsonInclude.Include.NON_EMPTY)@Transientprivate List<TMenu> children=new ArrayList<>();public TMenu() {}public TMenu(TMenu tMenu) {}
}
package com.zkdj.data.entity.pojo;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;import javax.persistence.*;
import java.io.Serializable;
/*** @description 系统角色表* @author gxf* @date 2023-05-29*/
@Entity
@Data
@Table(name="t_sys_role")
@ApiModel("系统角色表")
public class TRole implements Serializable {private static final long serialVersionUID = 1L;/*** 主键*/@Id@ApiModelProperty("主键")@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "id", nullable = false)private Integer id;/*** 角色名称*/@ApiModelProperty("角色名称")@Column(name="role_name")private String roleName;/*** 角色标识*/@ApiModelProperty("角色标识")@Column(name="role_type")private String roleType;/*** 角色描述*/@ApiModelProperty("角色描述")@Column(name="role_descrip")private String roleDescrip;/*** 创建时间*/@ApiModelProperty("创建时间")@Column(name="ctime")private String ctime;/*** 修改时间*/@ApiModelProperty("修改时间")@Column(name="utime")private String utime;/*** 角色权限ids*/@ApiModelProperty("角色权限ids")@Column(name="menu_ids")private String menuIds;public TRole() {}}
5.Jwt工具类
package com.zkdj.data.common.config.jwt.payload;import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.zkdj.data.entity.model.RcSysUserEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.util.Map;/*** @author Administrator*/
@Data
@ApiModel("jwt")
public class JwtPayLoad {private static final long serialVersionUID = 1L;@ApiModelProperty("过期时间")private String expTime;/*** 主键*/@Id@ApiModelProperty("主键")@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;/*** 账号*/@ApiModelProperty("账号")private String account;/*** 密码*/@ApiModelProperty("密码")private String password;/*** 真实姓名*/@ApiModelProperty("真实姓名")private String realname;/*** 角色id*/@ApiModelProperty("角色id")private String roleId;/*** 盐值*/@ApiModelProperty("盐值")private String salt;/*** 类型*/@ApiModelProperty("类型")private Integer type;/*** 创建时间*/@ApiModelProperty("创建时间")private String ctime;/*** 创建用户*/@ApiModelProperty("创建用户")private String cuser;/*** 更新时间*/@ApiModelProperty("更新时间")private String utime;/*** 令牌*/@ApiModelProperty("令牌")private String token;/*** 电话*/@ApiModelProperty("电话")private String tel;/*** 邮箱*/@ApiModelProperty("邮箱")private String email;/*** 启用禁用 0禁用1启用*/@ApiModelProperty("启用禁用 0禁用1启用")private Integer status;/*** 用户的键*/private String userKey;public JwtPayLoad() {}public JwtPayLoad(Long id, String roleId, String account, String realname) {this.id = id;this.roleId = roleId;this.account = account;this.realname = realname;}public JwtPayLoad(Long id, String roleId, String account, String realname,String expTime,String password,String salt,Integer type,String ctime,String cuser,String utime,String token,String tel,String email,Integer status,String userKey) {this.id = id;this.roleId = roleId;this.account = account;this.realname = realname;this.expTime = expTime;this.password = password;this.salt = salt;this.type = type;this.ctime = ctime;this.ctime = ctime;this.cuser = cuser;this.utime = utime;this.token = token;this.tel = tel;this.email = email;this.status = status;this.userKey = userKey;}/*** payload转化为map形式** @Date 2023/7/20 20:50*/public Map<String, Object> toMap() {Map<String, Object> map = BeanUtil.beanToMap(new JwtPayLoad(id, roleId, account, realname, expTime, password, salt,type, ctime, cuser, utime, token, tel, email, status, userKey), false, true);return map;}/*** payload转化为map形式** @Date 2023/7/20 20:50*/public static JwtPayLoad toBean(Map<String, Object> map) {if (map == null || map.size() == 0) {return new JwtPayLoad();} else {JwtPayLoad jwtPayLoad = BeanUtil.mapToBean(map, JwtPayLoad.class, true, new CopyOptions());return jwtPayLoad;}}
}
/*** Copyright 2018-2020 stylefeng & fengshuonan (sn93@qq.com)* <p>* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at* <p>* http://www.apache.org/licenses/LICENSE-2.0* <p>* Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.zkdj.data.common.config.jwt;import com.zkdj.data.common.config.jwt.payload.JwtPayLoad;
import com.zkdj.data.utils.UUIDUtil;
import com.zkdj.data.utils.date.DateUtil;
import io.jsonwebtoken.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;/*** <p>jwt token工具类</p>* <pre>* jwt的claim里一般包含以下几种数据:* 1. iss -- token的发行者* 2. sub -- 该JWT所面向的用户* 3. aud -- 接收该JWT的一方* 4. exp -- token的失效时间* 5. nbf -- 在此时间段之前,不会被处理* 6. iat -- jwt发布时间* 7. jti -- jwt唯一标识,防止重复使用* </pre>*/
public class JwtTokenUtil {static Integer DEFAULTSECS = 60*60*12; //默认过期时间10分钟private final static String DEFAULT_SECRET="eyJhbGciOiJIUzUxMiJ9";public final static String FORMAT="yyyy-MM-dd HH:mm:ss";/*** 生成token*/public static String createToken(JwtPayLoad jwtPayLoad) {Integer expiredSeconds = DEFAULTSECS;Date expirationDate = new Date(System.currentTimeMillis() + expiredSeconds * 1000);if(StringUtils.isNotBlank(jwtPayLoad.getExpTime())){expirationDate = DateUtil.getDateFormateStr(jwtPayLoad.getExpTime(),FORMAT);}jwtPayLoad.setExpTime(DateUtil.getDateTimeConvertStr(expirationDate,FORMAT));return generateToken(String.valueOf(jwtPayLoad.getId()),expirationDate,jwtPayLoad.toMap());}/*** 获取解析当前登录的用户token信息* @return*/public static JwtPayLoad getTokenJwtPayLoadInfo() {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();return JwtTokenUtil.getJwtPayLoad( request.getHeader("token"));}/*** 获取jwt的payload部分*/public static JwtPayLoad getJwtPayLoad(String token) {Claims claimFromToken = getClaimFromToken(token);return JwtPayLoad.toBean(claimFromToken);}/*** 解析token是否正确(true-正确, false-错误)*/public static Boolean checkToken(String token) {try {Jwts.parser().setSigningKey(DEFAULT_SECRET).parseClaimsJws(token).getBody();return true;} catch (JwtException e) {return false;}}/*** 验证token是否失效*/public static Boolean isTokenExpired(String token) {try {final Date expiration = getExpirationDateFromToken(token);if(null==expiration){return true;}return expiration.before(new Date());} catch (ExpiredJwtException expiredJwtException) {return true;}}/*** 获取jwt失效时间*/public static Date getExpirationDateFromToken(String token) {try {return getClaimFromToken(token).getExpiration();}catch (Exception ex){return null;}}/*** 生成token 核心方法*/public static String generateToken(String userId, Date expiredDate, Map<String, Object> claims) {final Date createdDate = new Date();if (claims == null) {return Jwts.builder().setSubject(userId).setIssuedAt(createdDate).setExpiration(expiredDate).signWith(SignatureAlgorithm.HS256, DEFAULT_SECRET).compact();} else {return Jwts.builder().setClaims(claims).setSubject(userId).setIssuedAt(createdDate).setExpiration(expiredDate).signWith(SignatureAlgorithm.HS256, DEFAULT_SECRET).compact();}}/*** 获取jwt的payload部分*/public static Claims getClaimFromToken(String token) {if (StringUtils.isEmpty(token)) {throw new IllegalArgumentException("token参数为空!");}return Jwts.parser().setSigningKey(DEFAULT_SECRET).parseClaimsJws(token).getBody();}public static void main(String[] args) {System.out.println(UUIDUtil.get32UUID());JwtPayLoad payLoad=new JwtPayLoad();
// payLoad.setUserId("103");
// payLoad.setExpTime("2021-12-26 23:50:50");payLoad.setToken("eyJhbGciOiJIUzI1NiJ9.eyJleHBUaW1lIjoiMjAyMy0wNi0wMiAwMzowNjowMiIsImlkIjo0LCJhY2NvdW50IjoiemtkaiIsInJlYWxuYW1lIjoiemtkaiIsInJvbGVJZCI6IjEiLCJjdGltZSI6IjIwMjMtMDUtMzEgMTg6MDA6NDMiLCJjdXNlciI6InprZGoiLCJ0ZWwiOiIxODYxMDA4NjEwMCIsImVtYWlsIjoiMTAwMDBAcXEuY29tIiwic3ViIjoiNCIsImlhdCI6MTY4NTYwMzE2MiwiZXhwIjoxNjg1NjQ2MzYyfQ.2pI28yqsG43gRkbsUv5UyH4OqSff3w3IASmNmF7lJRo");payLoad.setId(1L);String jwtsecret = "";String s = JwtTokenUtil.createToken(payLoad);
// String s = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMDMiLCJleHBUaW1lIjoiMjAyMS0xMi0xMSAwMDo1MDo1MCIsImN1c3RvbWVySWQiOm51bGwsInVzZXJOYW1lIjpudWxsLCJleHAiOjE2MzkxNTUwNTAsInVzZXJJZCI6IjEwMyIsImlhdCI6MTYzOTE1NDE0NiwiY3VzdG9tZXJOYW1lIjpudWxsfQ.WUlQlhG7DQUkMFNzm-uwD4lVCyeeNmRXY05tSeKYuEc";
// JwtPayLoad jwtPayLoad = getJwtPayLoad("eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMDUiLCJleHBUaW1lIjoiMjAyMS0xMi0yNyAyMTozNzowOCIsImN1c3RvbWVySWQiOm51bGwsInVzZXJOYW1lIjoieHlneHEiLCJleHAiOjE2NDA2MTIyMjgsInVzZXJJZCI6IjEwNSIsImlhdCI6MTY0MDYxMTYyOCwiY3VzdG9tZXJOYW1lIjpudWxsfQ.8lazFHdMdQP5K-iJCGdflCBZnlNOilXVSuGcA0mU1A0");JwtPayLoad jwtPayLoad = getJwtPayLoad(s);System.out.println("Secret:"+ jwtPayLoad.getToken());System.out.println("token是否正确:"+ JwtTokenUtil.checkToken(s)+jwtPayLoad.getExpTime());System.out.println("token是否失效:"+ JwtTokenUtil.isTokenExpired(s));System.out.println("token过期日期:"+ DateUtil.getDateTimeConvertStr(JwtTokenUtil.getExpirationDateFromToken(s),"yyyy-MM-dd HH:mm:ss"));}
}
权限
角色
用户
其他工具类见上篇文章