简单的鉴权登录-java后端实现部分(JWT令牌+拦截器Interceptor)

目录

一、实现大致流程

二、JWT令牌

1,JWT是什么?

2,,JWT令牌的组成

​编辑

3,JWT令牌在登录认证的应用

4,JWT令牌鉴权登录实现步骤

三、拦截器Interceptor

1,什么是拦截器?

2,拦截器Interceptor鉴权登录实现步骤

简单的鉴权登录结束 !!


一、实现大致流程

  • 在浏览器发起请求来执行登录操作,此时会访问登录的接口,如果访问的不是登录接口,为了安全,使其跳转到登录页面.如果登录成功之后,我们需要生成一个jwt令牌,将生成的 jwt令牌返回给前端。

  • 前端拿到jwt令牌之后,会将jwt令牌存储起来。在后续的每一次请求中都会将jwt令牌携带到服务端。

  • 服务端统一拦截请求之后,先来判断一下这次请求有没有把令牌带过来,如果没有带过来,直接拒绝访问,如果带过来了,还要校验一下令牌是否是有效。如果有效,就直接放行进行请求的处理。

二、JWT令牌

1,JWT是什么?

JWT (全称:Json Web Token)是一个开放标准(RFC 7519),它定义了一种简洁的、自包含的方式,用于作为 JSON 对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。

简洁:是指jwt就是一个简单的字符串。可以在请求参数或者是请求头当中直接传递。 自包含:指的是jwt令牌,看似是一个随机的字符串,但是我们是可以根据自身的需求在jwt令牌中存储自定义的数据内容。如:可以直接在jwt令牌中存储用户的相关信息。

简单点说就是一种认证机制,让后台知道该请求是来自于受信的客户端。JWT 主要用于用户登录鉴权

2,,JWT令牌的组成

JWT的组成: (JWT令牌由三个部分组成,三个部分之间使用英文的点来分割)

  • 第一部分:Header(头), 记录令牌类型、签名算法等。 例如:{"alg":"HS256","type":"JWT"}

  • 第二部分:Payload(有效载荷),携带一些自定义信息、默认信息等。 例如:{"id":"1","username":"Tom"}

  • 第三部分:Signature(签名),防止Token被篡改、确保安全性。将header、payload,并加入指定秘钥,通过指定签名算法计算而来。

    签名的目的就是为了防jwt令牌被篡改,而正是因为jwt令牌最后一个部分数字签名的存在,所以整个jwt 令牌是非常安全可靠的。一旦jwt令牌当中任何一个部分、任何一个字符被篡改了,整个令牌在校验的时候都会失败,所以它是非常安全可靠的。

简单的鉴权登录-java后端实现部分(JWT令牌+拦截器Interceptor)_第1张图片

3,JWT令牌在登录认证的应用

  1. 在浏览器发起请求来执行登录操作,此时会访问登录的接口,如果登录成功之后,我们需要生成一个jwt令牌,将生成的 jwt令牌返回给前端。

  2. 前端拿到jwt令牌之后,会将jwt令牌存储起来。在后续的每一次请求中都会将jwt令牌携带到服务端。

  3. 服务端统一拦截请求之后,先来判断一下这次请求有没有把令牌带过来,如果没有带过来,直接拒绝访问,如果带过来了,还要校验一下令牌是否是有效。如果有效,就直接放行进行请求的处理。

4,JWT令牌鉴权登录实现步骤

1,引入JWT依赖



    io.jsonwebtoken
    jjwt
    0.9.1

2,创建JWT工具类



public class JwtUtils {

    private static String signKey = "xxx";
    private static Long expire = 43200000L;

    /**
     * 生成JWT令牌
     * @param claims JWT第二部分负载 payload 中存储的内容
     * @return
     */
    public static String generateJwt(Map claims){
        String jwt = Jwts.builder()
                .addClaims(claims)
                .signWith(SignatureAlgorithm.HS256, signKey)
                .setExpiration(new Date(System.currentTimeMillis() + expire))
                .compact();
        return jwt;
    }

    /**
     * 解析JWT令牌
     * @param jwt JWT令牌
     * @return JWT第二部分负载 payload 中存储的内容
     */
    public static Claims parseJWT(String jwt){
        Claims claims = Jwts.parser()
                .setSigningKey(signKey)
                .parseClaimsJws(jwt)
                .getBody();
        return claims;
    }
}

3,三层架构实现登录成功,生成JWT令牌并返回

controller层

/**
 * 登录控制层
 *
 */
@RestController
@Slf4j
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    /**
     * 登录
     * @param user
     * @return
     */
    @PostMapping("/login")
    public Result login(@RequestBody User user){
        try {
            log.info("登录{}",user);
            String jwt = userService.login(user);
            return Result.success(true,"登录成功!!",jwt);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(false,"登录失败!!");
        }
    }
}

Service层

接口

public interface UserService {
    /**
     * 用户登录
     */
    String login(User user);
}

实现类

@Service
@Slf4j
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;


    /**
     * 用户登录
     */
    @Override
    public String login(User user) {
        if(user == null || user.getUsername() == null || "".equals(user.getUsername())
        || user.getPassword() == null || "".equals(user.getPassword())){
            throw new RuntimeException("用户不存在!!");
        }
        //根据用户查询用户的信息
        User dbUser = userMapper.findByUsername(user.getUsername());
        //判断密码是否正确
        if (!user.getPassword().equals(dbUser.getPassword())){
            throw new RuntimeException("用户名或密码错误!!");
        }
        //生成jwt令牌并返回
        HashMap claims = new HashMap<>();
        claims.put("id",dbUser.getId());
        claims.put("username",dbUser.getUsername());
        String jwt = JwtUtils.generateJwt(claims);
        return jwt;
    }
}

Mapper层

public interface UserService {
    /**
     * 用户登录
     */
    String login(User user);
}


==========xml===============

    

三、拦截器Interceptor

1,什么是拦截器?

        拦截器的主要是基于Java的反射机制,属于面向切面编程(AOP)的一种运用,就是在Service或者一个方法前调用一个方法,或者在方法后调用一个方法,甚至在抛出异常的时候做业务逻辑的操作。

        拦截器的作用类似于Servlet 中的Filter,都可以用于对处理器进行预处理和后处理。在Spring MVC 与Spring Boot 中使用拦截器一般是实现HandlerInterceptor 接口。

拦截器的作用:

  • 拦截请求,在指定方法调用前后,根据业务需要执行预先设定的代码。

2,拦截器Interceptor鉴权登录实现步骤

       1,定义拦截器

@Component
@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor{
     //目标资源方法执行前执行。 返回true:放行    返回false:不放行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1,先获取请求头
        String token = request.getHeader("token");
        response.setContentType("application/json;charset = UTF-8");
        ObjectMapper mapper = new ObjectMapper();
        //2,判断请求头是否存在
        if (token == null || "".equals(token)){
            //请求头不存在或者请求头为空
            log.info("token不存在");
            Result error = Result.error(false, "NOT_LOGIN");
            String result = mapper.writeValueAsString(error);
            response.getWriter().write(result);
            return false;
        }
        //3,请求头不正确
        try {
            Claims claims = JwtUtils.parseJWT(token);
        }  catch (Exception e)  {
            log.info("请求头不正确!!");
            Result error = Result.error(false, "NOT_LOGIN");
            String result = mapper.writeValueAsString(error);
            response.getWriter().write(result);
            return false;
        }
        return true;
    }
    
    //==========下面与登录无关,不用写==============

    //目标资源方法执行后执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle ... ");
    }

    //视图渲染完毕后执行,最后执行
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion .... ");
    }
}

注意:

  • preHandle方法:目标资源方法执行前执行。 返回true:放行 返回false:不放行
  • postHandle方法:目标资源方法执行后执行
  • afterCompletion方法:视图渲染完毕后执行,最后执行

2,注册配置拦截器

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private LoginCheckInterceptor loginCheckInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //定义拦截对象
        registry.addInterceptor(loginCheckInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/user/login");
    }
}

注意:

  • addPathPatterns("/**"):设置拦截器拦截的请求路径( /** 表示拦截所有请求)
  • .excludePathPatterns("/user/login"):不拦截的路径

简单的鉴权登录结束 !!

你可能感兴趣的:(javaweb,java,前端,开发语言)