这里JWT相关的工具类代码就不多展示了。这边可以在网上找到很多的JWTUtils模板。
对于前端我们写一个用于测试的几个页面。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>登录</title>
<script src="./script/jquery-3.7.1.min.js"></script>
</head>
<body>
<table>
<tr>
<td><input id="act" type="text"></td>
</tr>
<tr>
<td><input id="psd" type="password"></td>
</tr>
<td><button id="login">登录</button><button>注册</button></td>
</table>
</body>
<script>
var act = document.getElementById("act");
var psw = document.getElementById("psd");
$("#login").click(function(){
var act = $('#act').val();
var psw = $('#psd').val();
$.ajax('login',{
method: 'POST',
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify({uid: act,password: psw}),
success:function (result){
alert(JSON.stringify(result))
console.log(result)
},
error:function (result){
alert(result.data)
}
})
});
</script>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>管理页面</title>
</head>
<body>
<table>
<tr>
<td>测试成功</td>
<td>测试成功</td>
<td>测试成功</td>
</tr>
<tr>
<td>测试成功</td>
<td>测试成功</td>
<td>测试成功</td>
</tr>
<tr>
<td>测试成功</td>
<td>测试成功</td>
<td>测试成功</td>
</tr>
</table>
</body>
</html>
文件目录展示:
import com.cbq.springsecuritystudy6.entity.User;
import com.cbq.springsecuritystudy6.service.RoleService;
import com.cbq.springsecuritystudy6.service.UserService;
import com.cbq.springsecuritystudy6.vo.SecurityUser;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* @description: 定制化用户登录数据获取方式
* @author 长白崎
* @date 2023/9/19 11:28
* @version 1.0
*/
@Service
public class SecurityUserDetailServiceImpl implements UserDetailsService {
@Resource
UserService userService;
@Resource
private RoleService roleService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User userFromUid = userService.getUserFromUid(username);
if(userFromUid==null){
throw new UsernameNotFoundException("该用户不存在");
}
List<String> rolePermission = roleService.queryPermissionsByUserUid(username);
SecurityUser securityUser = new SecurityUser(userFromUid);
ArrayList<SimpleGrantedAuthority> authorityArrayList = new ArrayList<>();
rolePermission.stream().forEach((v)-> authorityArrayList.add(new SimpleGrantedAuthority(v)));
securityUser.setAuthorityList(authorityArrayList);
return securityUser;
}
}
import com.cbq.springsecuritystudy6.entity.User;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.List;
public class SecurityUser implements UserDetails {
private final User user;
private List<SimpleGrantedAuthority> authorityList;
/**
* 利用构造方法来注入User
* @param user
*/
public SecurityUser(User user) {
this.user = user;
}
/**
* 获取权限列表
* @return
*/
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorityList;
}
/**
* 设置权限列表
* @param authorityList
*/
public void setAuthorityList(List<SimpleGrantedAuthority> authorityList) {
this.authorityList = authorityList;
}
public User getUser() {
return user;
}
@Override
public String getPassword() {
String pws = user.getPassword();
user.setPassword(null);
return pws;
}
@Override
public String getUsername() {
return user.getUid();
}
/**
* 账号是否未过期
* @return
*/
@Override
public boolean isAccountNonExpired() {
return true;
}
/**
* 账号是否未锁定
* @return
*/
@Override
public boolean isAccountNonLocked() {
return true;
}
/**
* 账号是否未过期
* @return
*/
@Override
public boolean isCredentialsNonExpired() {
return true;
}
/**
* 账号是否可用
* @return
*/
@Override
public boolean isEnabled() {
return true;
}
}
这里就用Map来模拟Redis了。
import com.auth0.jwt.JWT;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.cbq.springsecuritystudy6.utils.JWTUtils;
import com.cbq.springsecuritystudy6.vo.SecurityUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
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;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@Slf4j
@Component
public class JwtCheckFilter extends OncePerRequestFilter {
//模拟Redis
public static Map<String,Object> redis = new HashMap<>();
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
//获取token
String authorization = request.getHeader("Authorization");
//如果token不存在可能是其他白名单的请求,这里直接放行
if(!StringUtils.hasText(authorization)){
//放行
filterChain.doFilter(request,response);
return;
}
DecodedJWT token = JWTUtils.getToken(authorization);
//获取uid
Claim uid = token.getClaim("uid");
System.out.println(uid.asString());
//判断是否为非法token
if(!JWTUtils.verify(authorization) && JWTUtils.isExpired(authorization)){
try {
throw new RuntimeException("非法Token");
}catch (Exception e){
}
}
String redisKey = "login:"+uid.asString();
//从redis里面获取对象
SecurityUser securityUser =(SecurityUser) redis.get(redisKey);
//如果redis里面没有相应的token,那么说明token非法
if(Objects.isNull(securityUser)){
throw new RuntimeException("您未登录");
}
//TODO 获取权限信息封装到Authentication中
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(securityUser,null,securityUser.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
//放行
filterChain.doFilter(request,response);
}
}