关注性能小课,成长不止一点点
做平台开发,登录功能是少不了的,之前我们分享过前端界面实现,今天我们以最简单方式来说说服务端登录接口实现。
▎框架
springboot + vue
▎功能
所有非登录接口做登录拦截
利用Session实现用户登录,且拦截器中会做是否登录判断,拦截未登录接口
注销功能实现
一个用户只能登录一次,另一个用户登录会注销之前登陆状态
▎登录原理
浏览器每次发请求都会带有一个JSESSIONID的cookie值,同一浏览器请求该域名或ip的接口他的值是一样的,服务端拿到这个session值,给他set一个带有唯一名字的属性,就表示他已登录。
▎登录接口实现
登录接口中,先去数据库查询该登录名和密码是否匹配,匹配后再拿到session,给该session设置一个属性名为LOGIN_NAME 的属性,该属性值不为空,就表示登录成功且登录状态一直存在。
@RequestMapping("/login")
public ResultBean<Object> login(HttpServletRequest request, HttpSession session, String username, String password) {
ServletContext application = session.getServletContext();
UserBean bean = userService.userIsExists(username,password);
if(bean != null){
session.setAttribute("LOGIN_NAME", username);
session.setMaxInactiveInterval(86400);
// 登录成功,则添加Session并存储登录用户名
return ResultBean.success("登录成功!");
}
return ResultBean.failed("登录账号或密码错误!");
}
▎登录拦截
这里我们用到了springboot拦截器,首先拦截了非登录接口,资源类请求我们不拦截。
InterceptConfig类
@Configuration
public class InterceptConfig implements WebMvcConfigurer {
private static final Logger logger = LoggerFactory.getLogger(InterceptConfig.class);
/**
* 添加Web项目的拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
logger.info("@Configuration 拦截器配置:");
// 对所有访问路径,都通过MyInterceptor类型的拦截器进行拦截
InterceptorRegistration ir = registry.addInterceptor(new MyInterceptor());
ir.excludePathPatterns("/login","/js/**","/html/**","/image/**","/css/**","/favicon.ico","/error"); //对应的不拦截的请求
ir.addPathPatterns("/**"); //拦截所有请求
}
}
MyInterceptor类
拦截之后我们再做处理,可以看出,在访问控制器方法前我们也是先拿到该session,然后拿到他的属性LOGIN_NAME ,如果不为空,我们会返回未携带token,请登录后再请求!
未登录的不允许访问,且返回未携带token
public class MyInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(MyInterceptor.class);
/**
* 访问控制器方法前执行
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
logger.info(new Date() + "--preHandle访问前:" + request.getRequestURL());
if(request.getRequestURI().contains("/login")){
return true;
}else{// 其他方法需要先检验是否存在Session
logger.info("LOGIN_NAME:" + request.getSession().getAttribute("LOGIN_NAME"));
logger.info("LOGIN_NAME:" + request.getSession().getId());
if (request.getSession().getAttribute("LOGIN_NAME") == null) {//未登录的不允许访问,且返回未携带token
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter out = null;
JSONObject res = new JSONObject();
res.put("status", "failed");
res.put("code", 300);
res.put("message", "未携带token,请登录后再请求!");
out = response.getWriter();
out.append(res.toString());
return false;
} else {
return true;
}
}
}
/**
* 访问控制器方法后执行
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
logger.info(new Date() + "--postHandle访问后:" + request.getRequestURL());
}
/**
* postHandle方法执行完成后执行,一般用于释放资源
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
logger.info(new Date() + "--afterCompletion释放:" + request.getRequestURL());
}
}
▎实验
有了上边两步后,启动服务,在未登录情况下,访问任何接口都会提示:未携带token,请登录后再请求!
登录前:

登录后:请求成功

通过这种方式肯定有他弊端,并不安全,同一个账号可能还会在不同浏览器同时使用,但是的确是最简单方式,而对我们开发一个测试平台来说,能满足。
并且现在常用的安全框架都是Shiro和SpringSecurity。
下一篇我们会来说说注销功能以及同一个账号再次登录时怎样才能踢出之前的登录状态。
END
欢迎加入我们:
扫码加入公开课学习交流群②
已在公开课学习交流群①
的小朋友请勿重复加群

免费技术支持微信:15712862196
咨询QQ:2657535456
咨询微信号:huice666

慧测公众号


