目录
7、修改CustomerUserDetailsService类
一、认证成功返回token
1、什么是token
2、token认证流程图
3 认证成功处理器返回token信息
(1)封装token返回的数据信息
package com.cizhu.utils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class LoginResult {
//用户编码
private Long id;
//状态码
private int code;
//token令牌
private String token;
//token过期时间
private Long expireTime;
}
(2)编写token工具类
package com.cizhu.utils;
import com.cizhu.entity.User;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Data
@ConfigurationProperties(prefix = "jwt")
@Component
public class JwtUtils {
//密钥
private String secret;
// 过期时间 毫秒
private Long expiration;
/**
* 从数据声明生成令牌
*
* @param claims 数据声明
* @return 令牌
*/
private String generateToken(Map<String, Object> claims) {
Date expirationDate = new Date(System.currentTimeMillis() + expiration);
return Jwts.builder().setClaims(claims).setExpiration(expirationDate).signWith(
SignatureAlgorithm.HS512, secret).compact();
}
/**
* 从令牌中获取数据声明
*
* @param token 令牌
* @return 数据声明
*/
public Claims getClaimsFromToken(String token) {
Claims claims;
try {
claims =
Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
} catch (Exception e) {
claims = null;
}
return claims;
}
/**
* 生成令牌
*
* @param userDetails 用户
* @return 令牌
*/
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
claims.put(Claims.SUBJECT, userDetails.getUsername());
claims.put(Claims.ISSUED_AT, new Date());
return generateToken(claims);
}
/**
* 从令牌中获取用户名
*
* @param token 令牌
* @return 用户名
*/
public String getUsernameFromToken(String token) {
String username;
try {
Claims claims = getClaimsFromToken(token);
username = claims.getSubject();
} catch (Exception e) {
username = null;
}
return username;
}
/**
* ()编写全局配置文件
* 在application.properties全局配置文件中自定义jwt属性。
* ()认证成功处理器类返回token数据
* 在原有的LoginSuccessHandler登录认证成功处理器类上加入jwt相关代码。
* 注意:在原有的基础上添加下面第~行的代码。
* 判断令牌是否过期
*
* @param token 令牌
* @return 是否过期
*/
public Boolean isTokenExpired(String token) {
Claims claims = getClaimsFromToken(token);
Date expiration = claims.getExpiration();
return expiration.before(new Date());
}
/**
* 刷新令牌
*
* @param token 原令牌
* @return 新令牌
*/
public String refreshToken(String token) {
String refreshedToken;
try {
Claims claims = getClaimsFromToken(token);
claims.put(Claims.ISSUED_AT, new Date());
refreshedToken = generateToken(claims);
} catch (Exception e) {
refreshedToken = null;
}
return refreshedToken;
}
/**
* 验证令牌
*
* @param token 令牌
* @param userDetails 用户
* @return 是否有效
*/
public Boolean validateToken(String token, UserDetails userDetails) {
User user = (User) userDetails;
String username = getUsernameFromToken(token);
return (username.equals(user.getUsername()) && !isTokenExpired(token));
}
}
package com.cizhu.config.security.handler;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.cizhu.entity.User;
import com.cizhu.utils.JwtUtils;
import com.cizhu.utils.LoginResult;
import com.cizhu.utils.ResultCode;
import io.jsonwebtoken.Jwts;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* 认证成功处理器
*/
@Component
public class LoginSuccessHandler implements AuthenticationSuccessHandler {
@Resource
private JwtUtils jwtUtils;
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
//设置响应编码格式
response.setContentType("applicaiton/json;charset=utf-8");
//换取当前登录用户信息
User user = (User)authentication.getPrincipal();
//生成token
String token = jwtUtils.generateToken(user);
//设置token签名密钥及过期时间
long expireTime = Jwts.parser() //获取DefaultJwtParser对象
.setSigningKey(jwtUtils.getSecret()) //设置签名的密钥
.parseClaimsJws(token.replace("jwt_", ""))
.getBody().getExpiration().getTime();//获取token过期时间
//创建登录结果对象
LoginResult loginResult = new LoginResult(user.getId(),
ResultCode.SUCCESS,token,expireTime);
//将对象转换成JSON格式,并消除循环引用
String result = JSON.toJSONString(user, SerializerFeature.DisableCircularReferenceDetect);
//获取输出流
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(result.getBytes(StandardCharsets.UTF_8));
outputStream.flush();
outputStream.close();
}
}
二、用户授权
1、修改Permission实体类
2、编写PermissionMapper接口 
3 编写PermissionMapper.xml映射文件
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.youmans.authority.entity.Permission">
<id column="id" property="id"/>
<result column="label" property="label"/>
<result column="parent_id" property="parentId"/>
<result column="parent_name" property="parentName"/>
<result column="code" property="code"/>
<result column="path" property="path"/>
<result column="name" property="name"/>
<result column="url" property="url"/>
<result column="type" property="type"/>
<result column="icon" property="icon"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
<result column="remark" property="remark"/>
<result column="order_num" property="orderNum"/>
<result column="is_delete" property="isDelete"/>
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, label, parent_id, parent_name, code, path, name, url, type, icon, create_time, update_time, remark, order_num, is_delete
</sql>
<select id="findPermissionListByUserId" resultType="com.youmans.authority.entity.Permission">
select
DISTINCT
p.id,p.parent_id,p.label,p.`code`,p.url,p.type,p.icon,p.remark,p.path,p.name
from
sys_user as u
left join sys_user_role as ur on u.id = ur.user_id
left join sys_role as r on ur.role_id = r.id
left join sys_role_permission as rp on rp.role_id = r.id
left join sys_permission as p on rp.permission_id = p.id
where u.id =#{userId}
order by p.id asc
</select>
4 编写PermissionService接口
5 编写PermissionService接口实现
6、User类添加权限菜单集合
7、修改CustomerUserDetailsService类
在CustomerUserDetailsService类原有的基础上添加相应的用户授权代码
package com.cizhu.config.security.service;
import com.cizhu.entity.Permission;
import com.cizhu.entity.User;
import com.cizhu.mapper.PermissionMapper;
import com.cizhu.service.IPermissionService;
import com.cizhu.service.IUserService;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 用户认证处理器类
*/
@Component
public class CustomerUserDetailsService implements UserDetailsService {
@Resource
private IUserService userService;
@Resource
private IPermissionService permissionService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//调用根据用户名查询用户信息的方法
User user = userService.findUserByUserName(username);
if (user ==null){
throw new UsernameNotFoundException("用户名或密码错误");
}
//查询当前用户拥有的权限列表
List<Permission> permissionList = permissionService.findPermissionListByUserId(user.getId());
//获取对应的权限编码
List<String> codeList = permissionList.stream()
.filter(Objects::nonNull)
.map(item -> item.getCode())
.filter(Objects::nonNull)
.collect(Collectors.toList());
//将权限编码列表转换成数组
String[] strings= codeList.toArray(new String[codeList.size()]);
//设置权限列表
List<GrantedAuthority> authorityList= AuthorityUtils.createAuthorityList(strings);
//将权限列表设置给user对象
user.setAuthorities(authorityList);
//设置该用户拥有的菜单信息
user.setPermissionList(permissionList);
return user;
}
}