登录与异常处理(Session/Cookie/JWT/Filter/Interceptor)

登录校验的实现思路是怎样的?

1.在员工登录成功后,需要将用户登录成功的信息,存起来,记录用户已经登录成功的标记。(登录标记)
2.在浏览器发起请求时,需要在服务端进行统一拦截,然后读取登录标记中的信息,如果有登录成功的信息,就说明用户登录成功,放行请求,如果发现登录标记中没有登录成功的标记,则给前端返回错误信息,跳转至登录页面。(统一拦截)
可以使用两种技术实现,Filter过滤器  以及 Interceptor 拦截器。 
在多次请求间共享数据: 会话跟踪技术

会话技术有哪些方式可以实现?

1). 客户端会话跟踪技术:Cookie
2). 服务端会话跟踪技术:Session
@RestController
@RequestMapping("/login")
public class LoginController {
    @Autowired
    private EmpService empService;

    @PostMapping
    public Result login(@RequestBody Emp emp, HttpSession session){
        Emp e = empService.login(emp);
        session.setAttribute("flag", "用户已登录");
        return e == null? Result.error("用户名或密码错误"): Result.success();
    }
}    

问题:

● 服务端集群环境下Session的共享问题。

● 移动端APP端无法使用Cookie。

JWT令牌组成部分有哪些,各自作用是什么?

第一部分:Header(头),作用:记录令牌类型、签名算法。
第二部分:Payload(有效载荷),作用:携带一些用户信息及过期时间(Base64编码)。
第三部分:Signature(签名),作用:防止Token被篡改、确保安全性。

base64UrlEncode(header):jwt令牌的第一部分。
base64UrlEncode(payload):jwt令牌的第二部分。
secret:签名所使用的密钥 

怎么使用JWT令牌?(依赖,创建,校验)

1). pom.xml 引入jwt的依赖

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

2). 生成JWT代码实现

public class JwtDemo {
    @Test
    public void genJwt(){
        Map<String,Object> claims = new HashMap<>();
        claims.put("id",1);
        claims.put("username","Tom");
        String jwt = Jwts.builder()
                .setClaims(claims) //执行第二部分负载, 存储的数据
                .signWith(SignatureAlgorithm.HS256, "itheima") //签名算法及秘钥
                .setExpiration(new Date(System.currentTimeMillis() + 12*3600*1000)) //设置令牌的有效期
                .compact();
        System.out.println(jwt);
    }
}

3).校验

    @Test
    public void parseJwt(){
        Claims claims = Jwts.parser()
                .setSigningKey("itheima")
            				.parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjU5OTk1NTE3LCJ1c2VybmFtZSI6IlRvbSJ9.EUTfeqPkGslekdKBezcWCe7a7xbcIIwB1MXlIccTMwo")
                .getBody();
        System.out.println(claims);
    }
注意事项:
●  JWT校验时使用的签名秘钥,必须和生成JWT令牌时使用的秘钥是配套的。
●  如果JWT令牌解析校验时报错,则说明 JWT令牌被篡改 或 失效了,令牌非法。

项目中在什么时候去生成令牌?

●  步骤: 
  ○  引入JWT工具类 
  public class JwtUtils {
    private static String signKey = "itheima";
    private static Long expire = 43200000L;	
    /**
     * 生成JWT令牌
     * @param claims JWT第二部分负载 payload 中存储的内容
     * @return
     */
    public static String generateJwt(Map<String, Object> 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;
    }
  }
  ○  登录完成后,调用工具类生成JWT令牌并返回 
  @RestController
  public class LoginController {
  	
      @Autowired
      private EmpService empService;
  	
      @PostMapping("/login")
      public Result login(@RequestBody Emp emp){
          Emp e = empService.login(emp);
          if(e != null){ //用户名密码正确
              Map<String,Object> claims = new HashMap<>();
              claims.put("id",e.getId());
              claims.put("username",e.getUsername());
              claims.put("name",e.getName());
  
              //生成JWT令牌
              String jwt = JwtUtils.generateJwt(claims);
              return Result.success(jwt);
          }
          return Result.error("用户名或密码错误");
      }
  }

当前端携带令牌访问资源时怎么去拦截校验令牌的合法性?

统一拦截请求,使用过滤器Filter或者拦截器Interceptor

过滤器具体使用的步骤是怎样的?

1). 定义类,实现 Filter接口,并重写doFilter方法
2). 配置Filter拦截资源的路径:在类上定义 @WebFilter  注解 
3). 在doFilter方法中输出一句话,并放行
4). 在引导类上使用@ServletComponentScan 开启 Servlet  组件扫描
疑问:
● 放行后访问对应资源,资源访问完成后,还会回到Filter中吗? 答案:会
● 如果回到Filter中,是重新执行还是执行放行后的逻辑呢?答案:执行放行后逻辑

拦截器具体使用的步骤是怎样的?

1.定义拦截器,实现HandlerInterceptor接口,并重写其所有方法。
2.注册拦截器

项目中异常是怎么处理的?具体怎么实现?

● 方案一:在Controller的方法中进行try…catch处理 (代码过于臃肿)
● 方案二:全局异常处理器
SpringMVC中提供了全局异常处理器接收所有Controller中产生的异常。一般定义在exception包下:
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * Exception异常分类
     *  - 运行时异常 : RuntimeException , 编译时无需处理 .
     *  - 编译时异常 : 非 RuntimeException , 编译时处理 .
     */
    @ExceptionHandler(Exception.class)
    public Result ex(Exception ex){
        ex.printStackTrace();
        return Result.error("系统繁忙, 请稍后重试 ... ");
    }

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-61XwxUYj-1691239428260)(img_60.png)]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值