基于 SpringBoot 前后端分离式
前后端分离
要实现前后端分离,需要考虑以下 2 个问题: 1. 项目不再基于 session 了,如何知道访问者是谁? 2. 如何确认访问者的权限? 前后端分离,一般都是通过 token 实现,本项目也是一样;用户登录时,生成 token 及 token 过期时间,token 与用户是一一对应关系,调用接口的时候,把 token 放到 header 或 请求参数中,服务端就知道是谁在调用接口。 源码先双手奉上: https://github.com/FENGZHIJIE1998/Auth-demo
各位客官觉得好用记得给个 Star!
项目架构图
导包、配置文件都省略。
第一步编写自己的拦截器 AuthInteceptor
```java
public class AuthInterceptor implements HandlerInterceptor { @Autowired private AuthService authService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
String token = TokenUtil.getRequestToken(request);
//如果token为空
if (StringUtils.isBlank(token)) {
setReturn(response,400,"用户未登录,请先登录");
return false;
}
//1. 根据token,查询用户信息
UserEntity userEntity = authService.findByToken(token);
//2. 若用户不存在,
if (userEntity == null) {
setReturn(response,400,"用户不存在");
return false;
}
//3. token失效
if (userEntity.getExpireTime().isBefore(LocalDateTime.now())) {
setReturn(response,400,"用户登录凭证已失效,请重新登录");
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
}
//返回错误信息
private static void setReturn(HttpServletResponse response, int status, String msg) throws IOException {
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtil.getOrigin());
//UTF-8编码
httpResponse.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=utf-8");
Result build = Result.build(status, msg);
String json = JSON.toJSONString(build);
httpResponse.getWriter().print(json);
}
} ```
第二步,将拦截器配置进 Spring
```java @Configuration public class InterceptorConfig implements WebMvcConfigurer {
@Bean
public AuthInterceptor authInterceptor() {
return new AuthInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 放行路径
List<String> patterns = new ArrayList();
patterns.add("/webjars/**");
patterns.add("/druid/**");
patterns.add("/sys/login");
patterns.add("/swagger/**");
patterns.add("/v2/api-docs");
patterns.add("/swagger-ui.html");
patterns.add("/swagger-resources/**");
patterns.add("/login");
registry.addInterceptor(authInterceptor()).addPathPatterns("/**")
.excludePathPatterns(patterns);
}
}
```
第三步:测试
Controller 层
```java /* * 登录校验 / @RestController("/") public class AuthController {
@Autowired
private AuthService authService;
/**
* 登录
*
* @param loginDTO
* @return token登录凭证
*/
@PostMapping("/login")
public Result login(@RequestBody LoginDTO loginDTO) {
String username = loginDTO.getUsername();
String password = loginDTO.getPassword();
//用户信息
UserEntity user = authService.findByUsername(username);
//账号不存在、密码错误
if (user == null || !user.getPassword().equals(password)) {
return Result.build(400, "用户名或密码错误");
} else {
//生成token,并保存到数据库
String token = authService.createToken(user);
TokenVO tokenVO = new TokenVO();
tokenVO.setToken(token);
return Result.ok(tokenVO);
}
}
/**
* 登出
*
* @param
* @return
*/
@PostMapping("/logout")
public Result logout(HttpServletRequest request) {
//从request中取出token
String token = TokenUtil.getRequestToken(request);
authService.logout(token);
return Result.ok();
}
/**
* 测试
*
* @param
* @return
*/
@PostMapping("/test")
public Result test( ) {
return Result.ok("恭喜你,验证成功啦,我可以返回数据给你");
}
}
```
编写 Service 层
```java @Service public class AuthServiceImpl implements AuthService {
@Autowired
private UserRepository userRepository;
@Override
public UserEntity findByUsername(String username) {
return userRepository.findByUsername(username);
}
//12小时后失效
private final static int EXPIRE = 12;
@Override
public String createToken(UserEntity user) {
//用UUID生成token
String token = UUID.randomUUID().toString();
//当前时间
LocalDateTime now = LocalDateTime.now();
//过期时间
LocalDateTime expireTime = now.plusHours(EXPIRE);
//保存到数据库
user.setLoginTime(now);
user.setExpireTime(expireTime);
user.setToken(token);
userRepository.save(user);
return token;
}
@Override
public void logout(String token) {
UserEntity userEntity = userRepository.findByToken(token);
//用UUID生成token
token = UUID.randomUUID().toString();
userEntity.setToken(token);
userRepository.save(userEntity);
}
@Override
public UserEntity findByToken(String token) {
return userRepository.findByToken(token);
}
} ```
然后启动项目即可
首先数据库保存一个用户,用户管理这里就不做啦。
我们来看看效果:使用 Swagger 查看效果
未登录状态下:
传递错误的 token:
登录成功:
传递正确的 token:
token 过期之后
总结:
如果你看过我那篇关于 Shiro 前后端分离的架构,其实很容易发现,这不就是简化版的 Shiro 吗?拦截、验证、返回错误信息。这就是思想上的一致。Shiro 底层是用 Filter(过滤器)、HandlerInterceptor 底层是 Interceptor(拦截器)。此外,本篇不仅仅可以实现登录拦截,对于权限拦截也是妥妥的,只需要再写一个拦截器,对权限进行验证,这里就不展开了。最主要还是前后端分离的思想,由前端控制路由,后端只负责返回对应信息,这肯定是发展趋势。
参考文献
- 集成WSH架构技术的Web应用研究与实现(西南交通大学·马崇启)
- 基于J2EE的中小企业通用网站的架构设计与开发(北京交通大学·李金龙)
- 基于Spring技术的大型视频网站后台上传系统的设计与实现(南京大学·徐悦轩)
- Spring轻量级框架在项目管理信息系统开发中的应用研究(西南交通大学·段培勇)
- 集成WSH架构技术的Web应用研究与实现(西南交通大学·马崇启)
- 基于SSH框架和ExtJs框架的资质管理系统的设计与实现(云南大学·职辉)
- 集成WSH架构技术的Web应用研究与实现(西南交通大学·马崇启)
- API服务中间件的设计与实现(电子科技大学·黄伟)
- 基于Spring技术的大型视频网站后台上传系统的设计与实现(南京大学·徐悦轩)
- 基于SpringCloud微服务治理平台的设计与实现(北京邮电大学·祁晖)
- 一种Web应用框架的设计与实现(·河北师范大学)
- Spring轻量级框架在项目管理信息系统开发中的应用研究(西南交通大学·段培勇)
- 基于Spring Cloud的培训商务系统的设计与实现(北京邮电大学·熊凯)
- 基于SSH框架的人力资源管理系统的设计与开发(电子科技大学·唐伟)
- 基于SSH框架和ExtJs框架的资质管理系统的设计与实现(云南大学·职辉)
本文内容包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主题。发布者:代码工厂 ,原文地址:https://bishedaima.com/yuanma/35846.html