博客系统 - 登陆功能
首先,博客系统分为两部分(以为我要说前端和后端吗?不是的,类似于博客园,是分为 博客的发布者和博客的浏览者)
对于博客的发布者,那么就需要进入到发布界面中,进行博客的发布,但是不能任何人都进入到这个界面啊,这时候就需要一个登陆界面和一个拦截器,用户要想进入发布或者编辑博客界面,必须进行登陆,并且每次进入这种管理员界面(指的就是编辑、发布博客的界面)前,都要经过拦截器,进行是否登陆的判断。
登陆界面: 这里就只是一个简单的登陆界面,只能登陆,没有用户注册的功能。(后期可以添加) uri为: http://localhost:8080/admin
(为什么输入上面那个网址,就能返回这个界面呢?)
前端代码: 这是只贴出重点代码。 (前端登陆界面,其实就是点击登陆按钮,提交了一个表单给了后端)
<form class="ui large form" method="post" action="#" th:action="@{/admin/login}"> // 请求方法 请求目的地址 必须写 <div class="ui segment"> <div class="field"> <div class="ui left icon input"> <i class="user icon"></i> <input type="text" name="username" placeholder="用户名"> // 输入框的 name属性要写上,后端就是通过着名称来获取的值,然后赋给了方法中的参数 </div> </div> <div class="field"> <div class="ui left icon input"> <i class="lock icon"></i> <input type="password" name="password" placeholder="密码"> </div> </div> <button class="ui fluid large teal submit button">登 录</button> </div> <div class="ui error mini message"></div> <div class="ui mini negative message" th:unless="${#strings.isEmpty(message)}" th:text="${message}">用户名和密码错误</div>
// // 如果返回的 message 不为null,或者!=”“, 就进行显示 这里用到thymeleaf的语法。message 是后端发回给前端的。 </form>
注意,登陆要进行校验,在前端要进行格式的校验;(通过js代码)
在后端要进行数据库的查询,登陆失败返回给前端失败信息。
后端代码:
@PostMapping("/login") // 前端是 post请求提交的表单,这里应该post方式,否则405错误,请求的方法不允许 public String login(@RequestParam(”username“) String username, // @RequestParam 用于绑定传来的请求中的 属性 可以传入属性的名字,
// 比如可以传入 username ,这时,就会将传来的username属性对应的值,赋值给方法中的该注解修改的参数
// 如果 传来的数据中,没有 @RequestParam 执行的参数,会报 400异常。 @RequestParam String password, HttpSession session, RedirectAttributes attributes){ User user=userService.checkUser(username,password); // 调用service, 进行数据库的查询if(user!=null){ // 如果查询结果不为 null, 说明账号密码正确 user.setPassword(null); session.setAttribute("user",user); // 添加到 session中,这就是为了后面的登陆拦截,检查是否登陆用的 return "admin/index"; ////////////////// // 进行了请求转发,返回index界面 }else{ attributes.addFlashAttribute("message","用户名或密码错误"); // 返回message信息 到前端界面中。 return "redirect:/admin"; // 重定向到了admin界面(就是登陆界面) } }
这里为什么登陆失败了,要重定向呢? 直接返回返回界面不行吗??? 重定向的目的是什么呢?? (这里重不重定向,问题也不大)
@GetMapping public String loginPage(){ return "admin/login"; }
改为请求失败,不进行重定向的方式。
@PostMapping("/login") public String login(@RequestParam String username, @RequestParam String password, HttpSession session, // RedirectAttributes attributes Map<String,String> map ){ User user=userService.checkUser(username,password); if(user!=null){ user.setPassword(null); // 将密码属性 置不置空 都可以 , 这可能是为了安全 session.setAttribute("user",user); return "admin/index"; }else{ // attributes.addFlashAttribute("message","用户名或密码错误"); map.put("message","用户名或密码错误"); // return "redirect:/admin"; return "admin/login"; } }
拦截器
定义拦截器,通过判断session中,是否有user属性,来判断用户是否已经登陆。
// 定义拦截器 public class LoginIntercept extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if(request.getSession().getAttribute("user")==null){ response.sendRedirect("/admin"); return false; } return true; } }
添加拦截器,只有注册拦截器到容器中,拦截器才会生效。
@Configuration public class WebConfig implements WebMvcConfigurer { // 要求必须要实现这个接口 @Override public void addInterceptors(InterceptorRegistry registry) { // 重写添加拦截器的方法 registry.addInterceptor(new LoginIntercept()).addPathPatterns("/admin/**"). // 表示这些路径下的请求都会经过拦截器 excludePathPatterns("/admin"). // 排除掉某些路径 即这些路径下的请求不会经过拦截器 excludePathPatterns("/admin/login"); } }
1)首先登陆界面肯定不能经过拦截器,不然,直接没法登陆了
2)其实,想一下,拦截器是怎么工作的?
拦截器如何工作的?
我们在登陆的时候,返回前端的 response http响应头中,就会有一个 set-cookie字段,字段中的值就会有一属性名为Jsessionid的属性,这个sessionid对应的就是后端的这个session的id. 如果账号密码正确,还会往这个session中,添加user属性,后面就通过判断session中是都有user属性,来判断是否登陆。(每个session都有一个唯一sessionid)
当后面访问博客的界面时,都会携带着这个sessionid,拦截器中的 request.getSeesion 就是根据传来的cookie中的这个sessionid来得到sessiond的,然后判断它里面是否有user这个属性,来判断用户是否登陆! (http是一个无状态的协议,通过cookie和session的配合,可以使得它 变得”有状态“,通过每次的请求中都携带着cookie. cookie和session的简单使用明白了把!!!)
if(request.getSession().getAttribute("user")==null){
在 yml配置文件中,配置日志的打印功能,SpringBoot中的日志框架的用的是 slf4j 接口, 和 logback实现类。(只要是个项目,就一定要打印日志)
logging:
level:
root: info // root 表示默认的级别
org.xixi: info // 也可以设置指定包名下的类的 日志输出级别
file:
name: myblogInfo.log // 日志存储的名称