精华内容
下载资源
问答
  • 用户登录校验
    2020-02-10 21:27:44

    后台实现校验用户接口

    我们在learn-auth-service中定义用户的校验接口,通过cookie获取token,然后校验通过返回用户信息。

    • 请求方式:GET

    • 请求路径:/verify

    • 请求参数:无,不过我们需要从cookie中获取token信息

    • 返回结果:UserInfo,校验成功返回用户信息;校验失败,则返回401

    代码:

    /**
      * 验证用户信息
      * @param token
      * @return
      */
    @GetMapping("verify")
    public ResponseEntity<UserInfo> verifyUser(@CookieValue("LY_TOKEN")String token){
        try {
            // 从token中解析token信息
            UserInfo userInfo = JwtUtils.getInfoFromToken(token, this.properties.getPublicKey());
            // 解析成功返回用户信息
            return ResponseEntity.ok(userInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 出现异常则,响应500
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
    }

    刷新token

    每当用户在页面进行新的操作,都应该刷新token的过期时间,否则30分钟后用户的登录信息就无效了。而刷新其实就是重新生成一份token,然后写入cookie即可。

    那么问题来了:我们怎么知道用户有操作呢?

    事实上,每当用户来查询其个人信息,就证明他正在浏览网页,此时刷新cookie是比较合适的时机。因此我们可以对刚刚的校验用户登录状态的接口进行改进,加入刷新token的逻辑。

    /**
      * 验证用户信息
      * @param token
      * @return
      */
    @GetMapping("verify")
    public ResponseEntity<UserInfo> verifyUser(@CookieValue("LY_TOKEN")String token, 
    HttpServletRequest request, HttpServletResponse response){
        try {
            // 从token中解析token信息
            UserInfo userInfo = JwtUtils.getInfoFromToken(token, this.properties.getPublicKey());
            // 解析成功要重新刷新token
            token = JwtUtils.generateToken(userInfo, this.properties.getPrivateKey(), 
    this.properties.getExpire());
            // 更新cookie中的token
            CookieUtils.setCookie(request, response, this.properties.getCookieName(), token, 
    this.properties.getCookieMaxAge());
    
            // 解析成功返回用户信息
            return ResponseEntity.ok(userInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 出现异常则,响应500
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
    }

     

    更多相关内容
  • 权限设计、用户登录校验

    千次阅读 2020-09-13 23:19:15
    此时如果要查询某一个用户对应的角色和权限,sql如下 select u.name user_name,r.name role_name,p.name privilege_name,p.uri uri from user u INNER JOIN user_role ur ON u.name = ur.user_name INNER JOIN ...

    准备数据

    CREATE TABLE `user` (
      `name` varchar(255) NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    CREATE TABLE `role` (
      `name` varchar(255) NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    CREATE TABLE `privilege` (
      `name` varchar(255) NOT NULL,
      `uri` varchar(255) NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    CREATE TABLE `user_role` (
      `user_name` varchar(255) NOT NULL,
      `role_name` varchar(255) NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    CREATE TABLE `role_privilege` (
      `role_name` varchar(255) NOT NULL,
      `privilege_name` varchar(255) NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    

    插入数据

    INSERT INTO `user` VALUES ('u1');
    INSERT INTO `user` VALUES ('u2');
    
    INSERT INTO `role` VALUES ('r1');
    INSERT INTO `role` VALUES ('r2');
    INSERT INTO `role` VALUES ('r3');
    
    INSERT INTO `privilege` VALUES ('p1', '/p1');
    INSERT INTO `privilege` VALUES ('p2', '/p2');
    INSERT INTO `privilege` VALUES ('p3', '/p3');
    INSERT INTO `privilege` VALUES ('p4', '/p4');
    
    INSERT INTO `user_role` VALUES ('u1', 'r1');
    INSERT INTO `user_role` VALUES ('u1', 'r2');
    INSERT INTO `user_role` VALUES ('u2', 'r2');
    INSERT INTO `user_role` VALUES ('u2', 'r3');
    
    INSERT INTO `role_privilege` VALUES ('r1', 'p1');
    INSERT INTO `role_privilege` VALUES ('r1', 'p2');
    INSERT INTO `role_privilege` VALUES ('r2', 'p2');
    INSERT INTO `role_privilege` VALUES ('r2', 'p3');
    INSERT INTO `role_privilege` VALUES ('r3', 'p3');
    INSERT INTO `role_privilege` VALUES ('r3', 'p4');
    

    此时如果要查询某一个用户对应的角色和权限,sql如下

    select
    	u.name user_name,r.name role_name,p.name privilege_name,p.uri uri
    from
    	user u
    INNER JOIN
    	user_role ur ON u.name = ur.user_name
    INNER JOIN
    	role r on ur.role_name = r.name
    INNER JOIN
    	role_privilege rp on r.name = rp.role_name
    INNER JOIN
    	privilege p on rp.privilege_name = p.name
    where
    	u.name = #{username}   
    

    1.通过Filter实现用户登录校验和权限校验

    在业务中,只有用户登录了,才能访问服务器中的资源

    分析:

    • 1.判断是登录后,才能访问的资源

      • 是:比如各种接口,比如某些jsp资源,判断用户是否登录
      • 否:比如login.jsp,、loginServlet、以及一些css/js文件,直接放行
    • 2.判断当前用户是否登录,判断session中是否有user

      • 有,用户已经登录,放行.(进行用户权限校验)
      • 否.跳转登录页面

    (1)用户登录校验

    package demo.filter;
    
    import demo.pojo.User;
    
    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class LoginFilter implements Filter {
    
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
        }
    
        // 登录校验
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) servletRequest;
    
            // 获取资源请求路径
            String uri = request.getRequestURI();
    
            // 判断当前访问资源,是否是是登录后,才能访问的资源
            String contextPath = request.getContextPath();
            if (uri.equals(contextPath + "/login.jsp") || uri.equals(contextPath + "/login")
                    || uri.startsWith(contextPath + "/css/") || uri.startsWith(contextPath + "/js/")) {
                // 在request中添加一个标识,告诉后面的过滤器,直接放行
                request.setAttribute("filterPass", true);
                filterChain.doFilter(servletRequest, servletResponse);
            } else {
                // 此资源需要用户登录后才能访问
                User user = (User)request.getSession().getAttribute("user");
                if(user != null){
                    //登录了。放行
                    filterChain.doFilter(servletRequest, servletResponse);
                }else{
                    //没有登录。跳转登录页面(使用重定向或者请求转发都可以实现)
                    // request.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
                    HttpServletResponse response = (HttpServletResponse)servletResponse;
                    response.sendRedirect(contextPath + "/login.jsp");
                }
            }
    
        }
    
        @Override
        public void destroy() {
    
        }
    }
    
    

    xml

    <!-- 登录过滤器 -->
      <filter>
        <filter-name>loginFilter</filter-name>
        <filter-class>demo.filter.LoginFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>loginFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
    

    登录页面

    package demo.controller;
    
    import demo.mapper.UserMapper;
    import demo.pojo.User;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    
    import javax.servlet.http.HttpServletRequest;
    
    @Controller
    public class UserController {
    
        @Autowired
        private UserMapper userMapper;
        
        
        // 跳转到users.jsp
        @RequestMapping(value = "login")
        public String toUsers(@RequestParam("name")String name, HttpServletRequest request) {
            User user = userMapper.queryUserByName(name);
            request.getSession().setAttribute("user", user);
            return "success";
        }
    
        // 跳转到users.jsp
        @RequestMapping(value = "p1")
        public String p1(HttpServletRequest request) {
            return "p1";
        }
    
        // 跳转到users.jsp
        @RequestMapping(value = "p2")
        public String p2(HttpServletRequest request) {
            return "p2";
        }
    
        // 跳转到users.jsp
        @RequestMapping(value = "p3")
        public String p3(HttpServletRequest request) {
            return "p3";
        }
    
        // 跳转到users.jsp
        @RequestMapping(value = "p4")
        public String p4(HttpServletRequest request) {
            return "p4";
        }
    
    }
    
    

    (2)通过filter实现权限控制

    package demo.filter;
    
    import demo.pojo.Privilege;
    import demo.pojo.Role;
    import demo.pojo.User;
    
    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    public class PrivilegeFilter implements Filter {
    
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
        }
    
        // 登录校验
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            
    		// 获取标识,判断是否为不需要进行权限校验的资源 
            Boolean pass = (Boolean)request.getAttribute("filterPass");
            if (null == pass || !pass.equals(true)) {
                User user = (User)request.getSession().getAttribute("user");
                
                // 判断用户是否有访问此资源的权限
                Set<String> uri = new HashSet<>();
                List<Role> roles = user.getRoles();
                for (Role role : roles) {
                    List<Privilege> privileges = role.getPrivileges();
                    for (Privilege privilege : privileges) {
                        uri.add(request.getContextPath() + privilege.getUri());
                    }
                }
    			// 用户的所有权限包含当前访问资源的uri
                if (uri.contains(request.getRequestURI())){
                    filterChain.doFilter(servletRequest, servletResponse);
                } else {
                    HttpServletResponse response = (HttpServletResponse)servletResponse;
                    response.sendRedirect(request.getContextPath() + "/login.jsp");
                }
                
            } else {
            	// 放pass为true时,此资源不用权限校验,直接放行
                filterChain.doFilter(servletRequest, servletResponse);
            }
        }
    
        @Override
        public void destroy() {
    
        }
    }
    

    因为在filter中,我们无法知道请求对应的是哪个controller中的哪个方法,所以我们只能通过用户和uri来进行权限控制


    2.通过拦截器实现用户登录校验和权限校验

    首先我们看下拦截器的如何被调用的。

    Web请求被DispatcherServlet截获后,会调用DispatcherServlet的doDispatcher方法。
    在这里插入图片描述
    当我们访问一个uri,映射器找不到对应的handler时,此时返回的HandlerExecutionChain为null(虽然我们设置的拦截器的路径为/**,拦截所有,但其实拦截器是通过映射器来调用的,只有当映射器找到具体的handler时,才会去找对应的拦截器)

    我们在通常情况下,设置DispatcherServlet的url为/,仅处理访问handler的请求,映射器也是如此,它无法去映射到一些静态资源,例如xx.jsp、xx.html、xx.css

    也就是说拦截器只能拦截通过映射器找到的handler,映射器无法映射到的资源,它都是不能拦截的,例如xx.jsp、xx.html、xx.css等等

    所以在实现用户登录校验时,我们只要关注那些handler(对应的uri)是可以通行的


    (1)使用拦截器实现用户登录校验
    用户没有登录时,仅能访问/login所对应的handler

    package demo.interceptors;
    
    import demo.pojo.User;
    import org.springframework.web.method.HandlerMethod;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Method;
    
    public class LoginInterceptor  implements HandlerInterceptor {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            String uri = request.getRequestURI();
            // 如果是login放行
            if (uri.equals(request.getContextPath() + "/login")) {
                return true;
            } else{
                User user = (User)request.getSession().getAttribute("user");
                if(user != null){
                    //登录了。放行
                    return true;
                }else{
                    //没有登录。跳转登录页面(使用重定向或者请求转发都可以实现)
                    response.sendRedirect(request.getContextPath() + "/login.jsp");
                    return false;
                }
            }
        }
    
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                               ModelAndView modelAndView) throws Exception {
        }
    
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
                throws Exception {
        }
    }
    
    

    path="/**"表示拦截所有层级的路径

    <!-- 注册自定义的拦截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!-- 拦截所有请求 -->
            <mvc:mapping path="/**"/>
            <!-- 自定义拦截器的全路径 -->
            <bean class="demo.interceptors.LoginInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
    

    (2)使用拦截器实现权限校验

    package demo.interceptors;
    
    import demo.pojo.Privilege;
    import demo.pojo.Role;
    import demo.pojo.User;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    public class PrivilegeInterceptor implements HandlerInterceptor {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            String uri = request.getRequestURI();
            // 如果是login放行
            if (uri.equals(request.getContextPath() + "/login")) {
                return true;
            } else{
                //进行权限校验
                User user = (User)request.getSession().getAttribute("user");
                Set<String> uris = new HashSet<>();
                List<Role> roles = user.getRoles();
                for (Role role : roles) {
                    List<Privilege> privileges = role.getPrivileges();
                    for (Privilege privilege : privileges) {
                        uris.add(request.getContextPath() + privilege.getUri());
                    }
                }
                if (uris.contains(request.getRequestURI())){
                    return true;
                } else {
                    response.sendRedirect(request.getContextPath() + "/login.jsp");
                    return false;
                }
            }
        }
    
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                               ModelAndView modelAndView) throws Exception {
        }
    
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
                throws Exception {
        }
    }
    
    
    <!-- 注册自定义的拦截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!-- 拦截所有请求 -->
            <mvc:mapping path="/**"/>
            <!-- 自定义拦截器的全路径 -->
            <bean class="demo.interceptors.LoginInterceptor"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <!-- 拦截所有请求 -->
            <mvc:mapping path="/**"/>
            <!-- 自定义拦截器的全路径 -->
            <bean class="demo.interceptors.PrivilegeInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
    

    3.总结过滤器和拦截器差别

    1.过滤器和拦截器的的触发时机不同,过滤器是进入容器后,但请求进入servlet之前进行预处理的,返回也是在servlet处理完后进行返回的,两者的执行顺序如下图
    在这里插入图片描述2.拦截器可以获取IOC容器中的各个bean,而过滤器就不行,因为拦截器是spring提供并管理的,spring的功能可以被拦截器使用,在拦截器里注入一个service,可以调用业务逻辑。而过滤器是JavaEE标准,只需依赖servlet api ,不需要依赖spring。
    在这里插入图片描述
    3.拦截器可以知道请求对应的是哪个handler(哪个Controller中的哪个method),而过滤器是无法知道的
    4.过滤器可以拦截所有的资源,拦截器一般只拦截handler

    展开全文
  • 在系统中,经常需要在处理用户请求之前和之后执行一些行为,例如检测用户的权限,或者将请求的信息记录到日志中。当然不仅仅这些,所以需要一种机制,拦截用户的请求,在请求的前后添加处理逻辑。 SpringMVC提供了...

    在系统中,经常需要在处理用户请求之前和之后执行一些行为,例如检测用户的权限,或者将请求的信息记录到日志中。当然不仅仅这些,所以需要一种机制,拦截用户的请求,在请求的前后添加处理逻辑。

    SpringBoot 提供了 Interceptor 拦截器机制,用于请求的预处理和后处理。在 SpringBoot 中定义一个拦截器有两种方法:第一种是实现 HandlerInterceptor 接口,或者继承实现了 HandlerInterceptor 接口的类(例如:HandlerInterceptorAdapter);第二种方法时实现 Spring 的 WebRequestInterceptor 接口,或者继承实现了 WebRequestInterceptor 接口的类。这些拦截器都是在Handler的执行周期内进行拦截操作的。

    1、HandlerInterceptor接口

    首先来看看 HandlerInterceptor 接口的源码:

    package org.springframework.web.servlet;
     
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.springframework.lang.Nullable;
     
    public interface HandlerInterceptor {
        default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            return true;
        }
     
        default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        }
     
        default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        }
    }

    如果要实现 HandlerInterceptor 接口,就要实现其三个方法,分别是:preHandle、postHandle、afterCompletion。

    (1)preHandle 方法在执行 Handler 方法之前执行。该方法返回值为 Boolean 类型,如果返回false,表示拦截请求,不在向下执行。而如果返回 true,表示放行,程序继续向下进行(如果后面没有其他 Interceptor,就会直接执行 Controller 方法)。所以,此方法可以对请求进行判断,决定程序是否继续执行,或者进行一些前置初始化操作及对请求做预处理。

    (2)postHandle 方法在执行 Handler 之后,返回 ModelAndView 之前执行。由于该方法会在前端控制器(DispatcherServlet)进行返回视图渲染之前被调用,所以此方法多被用于统一处理返回的视图,例如将公用的模型数据(例如导航栏菜单)添加到视图,或者根据其他情况制定公用的视图。

    (3)afterCompletion 方法在执行完Handler之后执行。由于是在 Controller 方法执行完毕后执行该方法,所以该方法适合进行统一的异常或者日志处理操作。

    相关博文:

    《JSP/Servlet实现简单的登录校验》

    《SpringMVC使用拦截器(Interceptor)实现用户登录校验》

    《SpringBoot拦截器的配置并实现用户登录校验》

    2、使用拦截器实现用户登录校验

    下面通过一个示例来使用拦截器完成登录控制,具体为拦截用户的请求,判断用户是否已经登录,如果用户没有登录,则跳转到 login 页面,如果用户已经登录,则放行。执行结果如下图:

    登录失败,提示失败信息:

     登录成功,进入首页:

     (1)创建项目 

    创建 SpringBoot 项目,项目结构如下图:

     (2)添加依赖

    使用Maven添加依赖文件,在 pom.xml 文件中,添加需要的依赖:

    <!-- Spring Boot 的 Web 依赖-->
    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- Thymeleaf 的依赖-->
    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

    (3)创建拦截器

    创建 com.pjb.interceptor 包,创建登录拦截器(LoginInterceptor.java),并实现HandlerInterceptor接口,实现其三个方法。这里主要以preHandle方法为主。

    package com.pjb.interceptor;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * 登录拦截器
     * @author pan_junbiao
     **/
    public class LoginInterceptor implements HandlerInterceptor
    {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
        {
            String uri = request.getRequestURI();
    
            //判断当前请求地址是否登录地址
            if(uri.contains("login") || uri.contains("toLoginPage"))
            {
                //登录请求,直接放行
                return true;
            }
            else
            {
                //判断用户是否登录
                if(request.getSession().getAttribute("userName")!=null)
                {
                    //说明已经登录,放行
                    return true;
                }
                else
                {
                    //没有登录,重定向到登录界面
                    response.sendRedirect(request.getContextPath() + "/toLoginPage");
                }
            }
    
            //默认拦截
            return false;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,Exception ex) throws Exception {
        }
    }

    (4)创建配置类

    创建 com.pjb.config 包,并创建 WebMvcConfig 类,实现 WebMvcConfigurer 接口;重写  addViewControllers 方法和 addInterceptors 方法;使用 @Configuration 注解,标注该类为配置类。

    了解WebMvcConfigurer配置接口的详解:

    《SpringBoot中的WebMvcConfigurer配置接口的详解》

    package com.pjb.config;
    
    import com.pjb.interceptor.LoginInterceptor;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    /**
     * Web MVC 配置类
     * @author pan_junbiao
     **/
    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer
    {
        /**
         * 控制器配置
         */
        @Override
        public void addViewControllers(ViewControllerRegistry registry)
        {
            registry.addViewController("/toIndexPage").setViewName("/index");
            registry.addViewController("/").setViewName("/index");
        }
    
        /**
         * 拦截器配置
         */
        @Override
        public void addInterceptors(InterceptorRegistry registry)
        {
            //注册Interceptor拦截器
            InterceptorRegistration registration = registry.addInterceptor(new LoginInterceptor());
            registration.addPathPatterns("/**"); //所有路径都被拦截
            registration.excludePathPatterns( //添加不拦截路径
                    "/toLoginPage", //登录页面
                    "/login",       //登录请求
                    "/**/*.html",   //html静态资源
                    "/**/*.js",     //js静态资源
                    "/**/*.css"     //css静态资源
            );
        }
    }

    (5)创建控制器

    创建 com.pjb.controller 包,创建登录控制器(LoginController.java),编写登录与登出方法。

    package com.pjb.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    import javax.servlet.http.HttpServletRequest;
    
    /**
     * 登录控制器
     * @author pan_junbiao
     **/
    @Controller
    public class LoginController
    {
        /**
         * 登录页面
         */
        @RequestMapping("/toLoginPage")
        public String toLoginPage()
        {
            //跳转至登录页面
            return "login.html";
        }
    
        /**
         * 登录
         */
        @RequestMapping(value = "/login", method = RequestMethod.POST)
        public String login(Model model, HttpServletRequest request, String userName, String password)
        {
            //验证登录信息
            if (userName.equals("pan_junbiao的博客") && password.equals("123456"))
            {
                //验证成功,记录Session信息
                request.getSession().setAttribute("userName", userName);
    
                //重定向到首页
                return "redirect:toIndexPage";
            }
            else
            {
                model.addAttribute("errorMsg", "账号或密码错误!");
            }
    
            //跳转至登录页面
            return toLoginPage();
        }
    
        /**
         * 登出
         */
        @RequestMapping(value = "/logout")
        public String logout(HttpServletRequest request)
        {
            //销毁session对象
            request.getSession().invalidate();
    
            //重定向到登录页面
            return "redirect:toLoginPage";
        }
    }

     (6)创建视图

    创建用户登录页面(Login.html)。

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>用户登录</title>
        <meta name="author" content="pan_junbiao的博客">
        <style>
            .txtBox{
                padding: 3px;
                width: 250px;
                font-size: 16px;
            }
        </style>
    </head>
    <body>
    <div align="center">请输入登录信息
        <form name="myForm" method="post" action="/login" onsubmit="SubmitLogin()">
            <table>
                <tr>
                    <td>用户姓名:</td>
                    <td><input type="text" name="userName" value="pan_junbiao的博客" class="txtBox" /></td>
                </tr>
                <tr>
                    <td>登录密码:</td>
                    <td><input type="password" name="password" value="123456" class="txtBox"/></td>
                </tr>
                <!-- 以下是提交、取消按钮 -->
                <tr>
                    <td>
                        <input type="submit" value="登录" />
                    </td>
                    <td>
                        <input type="reset" value="取消" />
                    </td>
                </tr>
            </table>
            <p style="color:red" th:text="${errorMsg}"></p>
        </form>
    </div>
    </body>
    <script>
        //提交登录
        function SubmitLogin() {
            //判断用户名是否为空
            if (!myForm.userName.value) {
                alert("请输入用户姓名!");
                myForm.userName.focus();
                return false;
            }
    
            //判断密码是否为空
            if (!myForm.password.value) {
                alert("请输入登录密码!");
                myForm.password.focus();
                return false;
            }
            return true;
        }
    </script>
    </html>

    创建首页(index.html)。

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
        <meta name="author" content="pan_junbiao的博客">
    </head>
    <body>
        <h1>首页</h1>
        <p>当前Session中保存的登录人名称:<span th:text="${session.userName}"/></p>
        <p>您好,欢迎访问 pan_junbiao的博客!</p>
        <p>博客地址:https://blog.csdn.net/pan_junbiao</p>
        <a href="logout" onclick="return confirm('确定注销吗?');">注销</a>
    </body>
    </html>

    展开全文
  • 在系统中,经常需要在处理用户请求之前和之后执行一些行为,例如检测用户的权限,或者将请求的信息记录到日志中。当然不仅仅这些,所以需要一种机制,拦截用户的请求,在请求的前后添加处理逻辑。 SpringMVC提供了...

    在系统中,经常需要在处理用户请求之前和之后执行一些行为,例如检测用户的权限,或者将请求的信息记录到日志中。当然不仅仅这些,所以需要一种机制,拦截用户的请求,在请求的前后添加处理逻辑。

    SpringMVC提供了Interceptor拦截器机制,用于请求的预处理和后处理。在SpringMVC中定义一个拦截器有两种方法:第一种是实现HandlerInterceptor接口,或者继承实现了HandlerInterceptor接口的类(例如:HandlerInterceptorAdapter);第二种方法时实现Spring的WebRequestInterceptor接口,或者继承实现了WebRequestInterceptor接口的类。这些拦截器都是在Handler的执行周期内进行拦截操作的。

    1、HandlerInterceptor接口

    首先来看看HandlerInterceptor接口的源码:

    package org.springframework.web.servlet;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.springframework.lang.Nullable;
    
    public interface HandlerInterceptor {
        default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            return true;
        }
    
        default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        }
    
        default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        }
    }

    如果要实现HandlerInterceptor接口,就要实现其三个方法,分别是:preHandle、postHandle、afterCompletion。

    (1)preHandle方法在执行Handler方法之前执行。该方法返回值为Boolean类型,如果返回false,表示拦截请求,不在向下执行。而如果返回true,表示放行,程序继续向下进行(如果后面没有其他Interceptor,就会直接执行Controller方法)。所以,此方法可以对请求进行判断,决定程序是否继续执行,或者进行一些前置初始化操作及对请求做预处理。

    (2)postHandle方法在执行Handler之后,返回 ModelAndView 之前执行。由于该方法会在前端控制器(DispatcherServlet)进行返回视图渲染之前被调用,所以此方法多被用于统一处理返回的视图,例如将公用的模型数据(例如导航栏菜单)添加到视图,或者根据其他情况制定公用的视图。

    (3)afterCompletion方法在执行完Handler之后执行。由于是在Controller方法执行完毕后执行该方法,所以该方法适合进行统一的异常或者日志处理操作。

    相关博文:

    《JSP/Servlet实现简单的登录校验》

    《SpringMVC使用拦截器(Interceptor)实现用户登录校验》

    《SpringBoot拦截器的配置并实现用户登录校验》

    2、使用拦截器实现用户登录校验

    下面通过一个示例来使用拦截器完成登录控制,具体为拦截用户的请求,判断用户是否已经登录,如果用户没有登录,则跳转到login页面,如果用户已经登录,则放行。执行结果如下图:

    登录失败,提示失败信息:

    登录成功,进入首页:

    (1)创建登录拦截器(LoginInterceptor.java),并实现HandlerInterceptor接口,实现其三个方法。这里主要以preHandle方法为主。

    package com.pjb.mvc.interceptor;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * 登录拦截器
     * @author pan_junbiao
     **/
    public class LoginInterceptor implements HandlerInterceptor
    {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
        {
            String uri = request.getRequestURI();
    
            //判断当前请求地址是否登录地址
            if(uri.contains("Login") || uri.contains("login"))
            {
                //登录请求,直接放行
                return true;
            }
            else
            {
                //判断用户是否登录
                if(request.getSession().getAttribute("user")!=null)
                {
                    //说明已经登录,放行
                    return true;
                }
                else
                {
                    //没有登录,跳转到登录界面
                    response.sendRedirect(request.getContextPath() + "/toLoginPage.action");
                }
            }
    
            //默认拦截
            return false;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,Exception ex) throws Exception {
        }
    }

    (2)编写完拦截器的逻辑后,需要在SpringMVC的核心配置文件springmvc.xml中配置该全局拦截器类:

    <!-- interceptor拦截器 -->
    <mvc:interceptors>
        <!-- 多个拦截器,顺序执行 -->
        <mvc:interceptor>
            <!-- /**表示所有url包括子url路径 -->
            <mvc:mapping path="/**"/>
            <bean class="com.pjb.mvc.interceptor.LoginInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

    (3)创建登录控制器(LoginController.java),编写登录与登出方法。

    package com.pjb.mvc.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import javax.servlet.http.HttpServletRequest;
    
    /**
     * 登录控制器
     * @author pan_junbiao
     **/
    @Controller
    public class LoginController
    {
        /**
         * 登录页面
         */
        @RequestMapping("/toLoginPage")
        public String toLoginPage()
        {
            //跳转至登录页面
            return "login.jsp";
        }
    
        /**
         * 登录
         */
        @RequestMapping(value = "/login", method = RequestMethod.POST)
        public String login(Model model, HttpServletRequest request, String user, String password)
        {
            //验证登录信息
            if (user.equals("pan_junbiao的博客") && password.equals("123456"))
            {
                //验证成功,记录Session信息
                request.getSession().setAttribute("user", user);
                //重定向到首页
                return "redirect:index.jsp";
            }
            else
            {
                model.addAttribute("errorMsg", "账号或密码错误!");
            }
            //跳转至登录页面
            return "login.jsp";
        }
    
        /**
         * 登出
         */
        @RequestMapping(value = "/logout")
        public String logout(HttpServletRequest request)
        {
            //销毁session对象
            request.getSession().invalidate();
    
            //重定向到登录页面
            return "redirect:login.jsp";
        }
    }

    (4)创建用户登录页面(Login.jsp)。

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>用户登录</title>
        <meta name="author" content="pan_junbiao的博客">
        <style>
            .txtBox{
                padding: 3px;
                width: 250px;
                font-size: 16px;
            }
        </style>
    </head>
    <body>
    <div align="center">
        <form name="form1" method="post" action="login.action" onsubmit="return SubmitLogin()">
            <table>
                <caption>用户登录</caption>
                <tr>
                    <th>账号:</th>
                    <td>
                        <input type="text" name="user" value="pan_junbiao的博客" class="txtBox"/>
                    </td>
                </tr>
                <tr>
                    <th>密码:</th>
                    <td>
                        <input type="password" name="password" class="txtBox" />
                    </td>
                </tr>
                <!-- 以下是提交、取消按钮 -->
                <tr>
                    <td colspan="2" style="text-align: center;">
                        <input type="submit" value="登录" />
                        <input type="reset" value="取消" />
                    </td>
                </tr>
            </table>
            <!-- 显示错误信息 -->
            <span style="color:red"><%=request.getAttribute("errorMsg") == null ? "" : request.getAttribute("errorMsg")%></span>
        </form>
    </div>
    </body>
    <script>
        //提交登录
        function SubmitLogin() {
            //判断用户名是否为空
            if (!form1.user.value) {
                alert("请输入用户名!");
                form1.user.focus();
                return false;
            }
    
            //判断密码是否为空
            if (!form1.password.value) {
                alert("请输入密码!");
                form1.password.focus();
                return false;
            }
            return true;
        }
    </script>
    </html>

    (5)创建首页(index.jsp)。

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
      <title>首页</title>
      <meta name="author" content="pan_junbiao的博客">
    </head>
    <body>
      <h1>首页</h1>
      <p>当前Session中保存的登录人名称:${sessionScope.user}</p>
      <p>您好,欢迎访问 pan_junbiao的博客!</p>
      <p>博客地址:https://blog.csdn.net/pan_junbiao</p>
      <a href="logout.action" onclick="return confirm('确定注销吗?');">注销</a>
    </body>
    </html>

    展开全文
  • AJAX实现用户登录校验

    千次阅读 2019-10-24 23:24:15
    实现对用户校验及其登录 效果: 源代码: jsp页面: <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> ...
  • 主要为大家详细介绍了PHP实现验证码校验功能,主要是利用PHP中的 SESSION功能来实现,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 拦截器统一处理用户的请求信息,包含网站的用户登录验证以及app的接口规范。
  • labview制作的密码登录小程序,带验证码输入校验
  • node express jwt实现一个用户登录校验以及权限拦截(用户认证与授权)服务端验证
  • 这是一个Spring-SpringMVC-Mybatis-Maven-MySQL架构的Java项目,主要实现登录校验功能。登录页面输入用户名和密码,点击登录按钮,查询数据库校验输入的内容,校验成功进入用户显示页面,将用户写入session,不成功...
  • 用户登录密码校验

    千次阅读 2019-01-23 09:10:44
    用户登录密码校验 思路:用户界面输入用户名和密码 数据库存储的是用户名及64位加密的密码 密码校验过程:1:用户在界面输入用户名及密码(在提交用户名、密码敏感字段中,最好不要出现username\password等字段)...
  • 登录用户权限校验
  • Jquery+Css+Html实现登录用户和密码进行前端校验以及用户登录功能 文章目录Jquery+Css+Html实现登录用户和密码进行前端校验以及用户登录功能前言一、什么是Jquery?二、什么是Css?三、什么是Html?四、Jquery前端...
  • 登录校验的实现

    千次阅读 2018-11-07 21:53:44
    在前端领域,一个避不开的话题就是登录验证的实现,本文将通过3种...## 用户登录的接口 type : post url : api/doLogin.php data : password email 响应体: ok 或则 fail ## 判断登录成功的接口 type : get url...
  • JAVA-用户登陆校验

    千次阅读 2019-07-25 16:12:23
    用户登录 前言: 在项目实际开发中,会遇到用户登录,注册等功能。下面是我自己写的用户登录的功能并贴上代码(此处代码仅做参考,实际还要参考项目需求,毕竟没有业务的代码叫demo)废话不多说直接上码 1 随机生成...
  • 网页登录界面进行登录后,如果不进行登录校验,则在其它页面无法知道该用户是否进行了登录。故需要对用户的登录进行校验,这里将介绍两种登录校验的方式。分别为利用自定义行为过滤器进行登录校验,另外一种是构建...
  • Python实现用户注册登录校验功能(面向对象方法)

    万次阅读 多人点赞 2019-03-05 23:03:12
    用户登录&gt;分别提示用户输入用户名和密码,用户名为seven,密码为123,或者用户名为alex,密码为456。提示登录成功,并结束程序。否则提示失败原因,并提示重新输入,最多三次机会。 &lt;注册功能&gt;...
  • python123 验证码校验

    2020-12-21 21:14:33
    用户登录网站经常需要输入验证码,验证码包含大小写字母和数字,随机出现。用户输入验证码时不区分大小写,只要各字符出现顺序正确即可通过验证。请写一个程序完成验证码的匹配验证,假设当前显示的验证码是’Ks3V’...
  • 利用struts技术,用校验校验用户提交信息的一个简单的用户注册登录的例子。用的数据库是2005的
  • 主要为大家详细介绍了javascript使用正则表达式实现注册登入校验,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • python校验用户登录信息

    千次阅读 2019-03-31 19:50:44
    用户输入用户名,密码后对信息进行校验 1.用户名长度在3-8个字符 2.用户名中只能出现英文字母和数字 3.密码长度必须是6位 4.密码必须由纯数字组成 分析: 1.信息使用input操作获取 2.定义自定义异常,描述非法信息 3...
  • 所以在这些接口正式执行前,我们需要先检查当前是否有管理员用户登录; 而,为了提高效率,在【Spring Boot电商项目27:商品分类模块六:统一校验管理员身份;(选用【J2EE中的过滤器】来实现需求;重难点是...
  • 登录注册案例 1.登录注册第一步——创建模型生成数据表: (1)名为mucis的app下的models.py文件中创建: from django.db import models # Create your models here. class User(models.Model): username = models...
  • 前端-登录实时校验

    2022-04-13 08:18:14
    写了一个登录验证,想要实现功能: 密码输入框右侧提醒,一边输入,一边校验密码输入的格式是否正确,如果不正确,输入框右侧出现提醒,并且输入框的边框变红,直到输入格式正确才恢复正常。 实加粗样式现的效果: ...
  • 登录拦截器:在这里介绍的登录拦截器主要有两个功能作用,禁止未登录或登录信息失效状态下对系统进行操作,同时实现用户登录信息的过期机制。 我们通常会将用户信息保存在session或cookie中,而对于session来讲设置...
  • JavaScript实现用户登录验证进阶篇

    千次阅读 2018-05-08 10:25:25
    最近刷到有关实现简单的用户登录验证的前端题,由于平时基础实践较少,大多使用框架,特总结此博客:一、先来看一段简单的用户登录验证:body{  text-align: center; } #content{  /*水平居中外盒子*/  display: ...
  • javaweb用户验证码登录session例子

    热门讨论 2015-10-04 10:31:08
    javaweb中用到的用户密码验证码一体的登录例子,主要是利用session原理的例子。
  • 小程序登录操作校验是否登录

    千次阅读 2022-03-30 15:07:04
    // 登录操作校验是否登录 checkLogin() { let that = this return new Promise((resolve, reject) => { //如果是小程序页面 || 有appid并且是微信浏览器 if(util.isMiniPg() || (that....
  • 本文实例为大家分享了python实现用户名密码校验的具体代码,供大家参考,具体内容如下 需要实现功能 输入用户名密码 ; 认证成功后显示 欢迎信息 ; 连续输错三次后 锁定 ; readme: ... #打开用户
  • 主要介绍了MVC使用Controller代替Filter完成登录验证即Session校验,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 145,832
精华内容 58,332
关键字:

用户登录校验