Fork me on GitHub

SpringBoot+Mybatis+PostMan(五):token登陆认证过程一(token生成与认证)

Springboot+Mybatis+redis+postman项目实战总目录*

SpringBoot+Mybatis+PostMan(五):token登陆认证过程二(redis缓存引入)

SpringBoot+Mybatis+PostMan(六):token登陆认证过程三(redis封装与干掉原来session,避免用户重复登陆)

番外篇:SpringBoot 用户注册时经MD5加密存入数据库

 

第二篇章:用户角色权限访问控制

SpringBoot+Mybatis+PostMan(七):用户角色权限访问控制入门(数据模拟实现,不带数据库)

SpringBoot+Mybatis+PostMan(八):用户角色权限访问控制一(数据库用户角色表查询组合)

SpringBoot+Mybatis+PostMan(九):用户角色权限访问控制二(加入资源表和资源角色对应表)

SpringBoot+Mybatis+PostMan(十):用户角色权限访问控制三(禁用session、启用token并集成redis)

 

当我们访问某个网站时,我们首先只能进入到登陆页面,系统其他页面时访问不进去的,所以这里需要通过拦截器实现拦截功能,只能对外界暴露注册和登陆页面,其余页面一律拦截住。用户登陆时将信息传递到服务器端,服务器会查询此用户在服务器是否有session,如果没有,那么就将用户拦截在登陆页面,如果用户信息在服务器端时存在的,那么服务器端为其开辟一个session内存,并为其生成一个sessionID。

这里用到的知识有拦截器、token认证等等,接下来就进行token认证过程。

项目代码获取地址:https://github.com/yeyuting-1314/testdemo_insert_page_token.git

一、准备工作

1. 首先添加依赖,这里拦截需要用到JWT工具,需要我们手工导入

 <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.4.0</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>

2. 接下来实现token工具类,实现token生成、获取特定属性、获取请求,以及获取到token。

@Component
public class TokenUtil {
    /*
    * 生成token
    * */
    public String generateToken(User user){
        Date start  = new Date() ;
        long currentTime = System.currentTimeMillis() + 60*60*1000 ; //一小时的有效时间
        Date end = new Date(currentTime) ;
        String token = "" ;
        token = JWT.create()
                .withAudience(Integer.toString(user.getId()))
                .withAudience(user.getUserName())
                .withIssuedAt(start)
                .withExpiresAt(end)
                .sign(Algorithm.HMAC256(user.getPassword()));
        return token ;
    }

    /*
    * 获取指定token中某个属性值
    * */
    public static String get(String token , String key){
        List<String> list = JWT.decode(token).getAudience() ;
        String userId = list.get(0) ;
        return userId ;
    }
    /*
    * 获取request
    * */
    public static HttpServletRequest getRequest(){
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return requestAttributes == null ? null : requestAttributes.getRequest() ;
    }

    /*
    * 获取token
    * */
    public String getToken(HttpServletRequest request)  {
        Cookie[] cookies = request.getCookies() ;
        for(Cookie c : cookies){
            if(c.getName() == "token"){
                return c.getValue() ;
            }
        }
        return null ;
    }

}

3. 自定义拦截器类,preHandle这个方法会业务层执行前先行执行,用于检查该请求是否带有token,如果有的话就放行,让其进行token认证,如果没有的话就拦截住,重定向到登陆页面(一般这种情况值我们要访问除了login和loginCheck两个页面的其他页面时,会被拦截住,重定向到登陆页面,后面会有演示)

//自定义拦截器类

public class AuthenticationInterceptor implements HandlerInterceptor {

    @Autowired TokenUtil tokenUtil ;

    @Override
    public boolean preHandle (HttpServletRequest request ,
                              HttpServletResponse response , Object o )throws Exception{
        //检查请求中是否存在token , 如果不存在就直接跳转到登陆页面
        String token = tokenUtil.getToken(request) ;
        if(StringUtil.isEmpty(token)){
            System.out.println("不存在token");
            response.sendRedirect("/login");
            return false ;
        }
        return true ;
    }


}

4. 拦截器实现,将需要拦截的页面进行相应拦截

@Configuration
public class MVCConfig implements WebMvcConfigurer {


    @Bean
    public HandlerInterceptor authenticationInterceptor(){

        return new AuthenticationInterceptor();
    }
    /*
    * 静态资源映射
    * */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry){
        registry.addResourceHandler("/static/**")
                .addResourceLocations("classpath:/static/") ;
    }
    @Override
    public void addInterceptors (InterceptorRegistry registry){
       registry.addInterceptor(authenticationInterceptor())
                //表示拦截所有请求
                .addPathPatterns("/*")
                //表示取消对特定路径的拦截
                .excludePathPatterns("/login")
                .excludePathPatterns("/loginCheck");
                //这里一定不要写成/**/*.js的形式,spring boot无法识别
                //取消对static目录下静态资源的拦截
               // .excludePathPatterns("/static/**") ;
    }

}

二、 这样一来准备工作就做好了,接下来就是业务层的实现了。

 1. controller层实现

@GetMapping("/login")
    public String test1(){
        System.out.println(PropertiesUtil.class.getClassLoader().
                getResource("").getPath());
        return "登陆界面" ;
    }

    @PostMapping("/loginCheck")
    @ResponseBody
    public  Result login(@RequestBody User user , HttpServletResponse response){
        Result result = userService.loginCheck(user , response) ;
        return result ;
    }

2. service层

public Result loginCheck(User user , HttpServletResponse response);
public Result loginCheck(User user , HttpServletResponse response){
        User user1 = userMapper.selectByName(user.getUserName()) ;
        if(user1 == null ){
            //response.sendRedirect("/login");
            return Results.failure("用户不存在,") ;
        }
        if(!user1.getPassword().equals(user.getPassword())){
            return Results.failure("密码输入错误") ;
        }
        String token = tokenUtil.generateToken(user1) ;
        System.out.println("token:" + token);
        Cookie cookie = new Cookie("token" , token) ;
        // 设置cookie的作用域:为”/“时,以在webapp文件夹下的所有应用共享cookie
        cookie.setPath("/");
        response.addCookie(cookie);
        System.out.println("cookie:"+cookie);
        return Results.success("登陆成功") ;

    }

这样一来,业务层代码逻辑也书写完毕,接下来利用postman实现前端模拟。

数据库内容如下:

 1. 若访问除了login和loginCheck外的其他页面,会被拦截回到登陆页面。

 

 2. 如果用户名正确密码错误:

 

 3. 用户名不存在

 

 4. 用户名密码均正确,成功登陆。

 这样一来,token认证登陆这一功能就实现了。

至此,结束。

posted @ 2021-01-14 10:58  叶语婷  阅读(2624)  评论(1编辑  收藏  举报