spring Aop实现身份验证和springboot异常统一处理

一、spring Aop身份验证

一般,如果用户没有登录的话,用户只可以查看商品,但是其他的,比如支付等是不能够进行操作的,这个时候,我们就需要用到用户拦截, 或者说身份验证了。

首先定义一个类AuthorizeAspect,以@Aspect注解。

然后把所有以Controller声明为切点,但排除UserController,因为这个Controller就是验证用户登录的Controller。

  @Pointcut("execution(public * com.sihai.controller *.*(..))"+
    "&& !execution(public * com.sihai.controller.UserController.*(..))")
    public void verify(){}

最后对这个切点做一些前置处理,因为用户登录后,按照我们之前写的逻辑,cookie和redis中应该含有用户的信息,所以现在查询这两个地方,来验证用户有没有登录。

   @Before("verify()")
    public void doVerify(){
        ServletRequestAttributes attributes=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request=attributes.getRequest();

        //查询cookie
        Cookie cookie= CookieUtil.get(request,CookieConstant.TOKEN);
        if (cookie==null){
            log.warn("Cookie中查不到token");
            throw new   AuthorizeException();
        }

        //去redis查询,这个下面的redis用到的是springboot的redis工具类
        String tokenValue=redisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_PREFIX,cookie.getValue()));
        if (StringUtils.isEmpty(tokenValue)){
            log.warn("Redis中查不到token");
            throw new   AuthorizeException();
        }
    }

完整代码如下:

@Aspect
@Component
@Slf4j
public class AuthorizeAspect {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Pointcut("execution(public * com.sihai.controller.  *.*(..))"+
    "&& !execution(public * com.sihai.controller.  UserController.*(..))")
    public void verify(){}

    @Before("verify()")
    public void doVerify(){
        ServletRequestAttributes attributes=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request=attributes.getRequest();

        //查询cookie
        Cookie cookie= CookieUtil.get(request,CookieConstant.TOKEN);
        if (cookie==null){
            log.warn(" Cookie中查不到token");
            throw new   AuthorizeException();
        }

        //去redis查询
        String tokenValue=redisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_PREFIX,cookie.getValue()));
        if (StringUtils.isEmpty(tokenValue)){
            log.warn("  Redis中查不到token");
            throw new   AuthorizeException();
        }
    }

}

二、springboot统一异常处理

  • 自定义异常类

从以上代码中可以看到,如果用户没有登陆,就会抛出一个 AuthorizeException的异常,这是一个自定义的异常。这个异常很简单,只有一个简单的定义,为运行时异常

public class AuthorizeException extends RuntimeException {}

之后我们需要定义一个对这个异常的处理器 ExceptionHandler,当扑获到这个异常,说明用户没有登陆,那就重新调到登陆界面(访问处理登陆的Controller)。

  • 创建全局异常处理类:通过使用@ControllerAdvice定义统一的异常处理类,而不是在每个Controller中逐个定义。@ExceptionHandler用来定义函数针对的异常类型,最后将Exception对象和请求URL映射到error.html
@ControllerAdvice
public class  ExceptionHandler {

    @Autowired
    private ProjectUrlConfig projectUrlConfig;

    //拦截登录异常
    @ExceptionHandler(value =  AuthorizeException.class)
    public ModelAndView handlerAuthorizeException(){
        ModelAndView mav = new ModelAndView();
        mav.addObject("exception", e);
        mav.addObject("url", req.getRequestURL());
        mav.setViewName(DEFAULT_ERROR_VIEW);
        return mav;
    }
}
  • 实现error.html页面展示:在templates目录下创建error.html,将请求的URL和Exception对象的message输出。
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8" />
    <title>统一异常处理</title>
</head>
<body>
    <h1>Error Handler</h1>
    <div th:text="${url}"></div>
    <div th:text="${exception.message}"></div>
</body>
</html>

启动该应用,访问:http://localhost:8080/hello,可以看到如下错误提示页面。

原文发布于微信公众号 - 好好学java(SIHAIloveJAVA)

原文发表时间:2018-10-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏全栈

拦截器的使用

32730
来自专栏阿杜的世界

Spring MVC旧项目的日志埋点

7310
来自专栏noteless

eclipse 创建maven 项目 动态web工程完整示例 maven 整合springmvc整合mybatis

如果搜索不到内容,或者有报错信息(index downloads are disabled ,search results may be incomplete)

21520
来自专栏个人分享

spark单机模式简单搭建

待安装列表 hadoop hive scala spark 一.环境变量配置: ~/.bash_profile PATH=$PATH:$HOME/bin

61910
来自专栏帘卷西风的专栏

Cmake在windows支持预编译头文件(stdafx.h)

      最近一直在研究cmake构建项目,之前接触cmake的时候就感觉不太喜欢cmake,觉得它太乱了,产生了太多的中间文件,产生的项目文件也不是特别友好...

15620
来自专栏酷玩时刻

SpringBoot 2.x 集成QQ邮箱、网易系邮箱、Gmail邮箱发送邮件

发送模板邮件使用的方法与发送HTML邮件的方法一致。只是发送邮件时使用到的模板引擎,这里使用的模板引擎为Thymeleaf。

34230
来自专栏乐沙弥的世界

publickey,gssapi-with-mic,Unspecified GSS failure

        最近的MHA配置时碰到了Permission denied (publickey,gssapi-with-mic,password)这个错误提示...

16620
来自专栏JavaEE

ssm整合案例(超级详细)spring+springmvc+mybatis整合案例

600100
来自专栏Ryan Miao

SpringCloud学习5-如何创建一个服务提供者provider

14230
来自专栏猿天地

spring boot整合dubbox进行服务拆分

Dubbo是一个来自阿里巴巴的开源分布式服务框架,当当根据自身的需求,为Dubbo实现了一些新的功能,包括REST风格远程调用、Kryo/FST序列化等等。并...

1.9K100

扫码关注云+社区

领取腾讯云代金券