SpringBoot中使用AOP切面编程实现登录拦截

使用AOP切面编程实现登录拦截

1. 首先实现一个登录注册功能

以下代码仅供参考

  • 控制层
java 复制代码
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;
    @PostMapping("/register")
    public Result register(@RequestBody UserDto userDto) {
        userService.addUser(userDto);
        return Result.success("注册成功");
    }

    @PostMapping("/login")
    public Result<UserLoginVo> login(@RequestBody UserDto userDto) {
        UserLoginVo userLoginVo = userService.login(userDto);
        return Result.success(userLoginVo);
    }
}
  • 业务层
java 复制代码
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Resource
    private RedisTemplate<String,String> redisTemplate;
    /**
     * 新增用户/注册
     * @param userDto
     */
    public void addUser(UserDto userDto) {
        User user = userMapper.selectByUserName(userDto.getUsername());
        if (user != null) {
            throw new BusinessException(ResponseCodeEnum.CODE_601);
        }
        user = new User();
        BeanUtils.copyProperties(userDto, user);
        user.setCreateTime(new Date());
        user.setLoginTime(new Date());
        userMapper.insert(user);
    }

    @Override
    public UserLoginVo login(UserDto userDto) {
        User user = userMapper.selectByUserNameAndPassword(userDto.getUsername(),userDto.getPassword());
        if (user == null) {
            throw new BusinessException("用户名或密码错误");
        }
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set("loginDemo:user:token:" + token, user.getId().toString());
        UserLoginVo userLoginVo = new UserLoginVo();
        userLoginVo.setUser(user);
        userLoginVo.setToken(token);
        return userLoginVo;
    }
}
  • mapper层
java 复制代码
@Mapper
public interface UserMapper extends BaseMapper<User>{


    void addUser(User user);
    
    @Select("select * from user where username = #{username}")
    User selectByUserName(String username);

    User selectByUserNameAndPassword(String username,String password);
}
  • UserMapper.xml
xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.kkk.mapper.UserMapper">

    <insert id="addUser">
        INSERT INTO user (
            username,
            password,
            email
        ) VALUES (
                     #{username},
                     #{password},
                     #{email}
                 )
    </insert>
    <select id="selectByUserNameAndPassword" resultType="com.kkk.domain.entity.User">
        select * from user
        <where>
            <if test="username != null and username != ''">
                and user.username = #{username}
            </if>
            <if test="password != null and password != ''">
                and user.password = #{password}
            </if>
        </where>
    </select>

</mapper>

以上代码仅供参考,具体逻辑可以根据自己的业务来实现

2. 补充介绍

以上提供的示例代码逻辑大致为用户登录后根据UUID生成一个token,接着将token作为唯一标识键存入redis缓存中,值为用户id,之后可以根据用户请求头中的token去redis中获取用户id,当然你也可以根据自己的实际需求来。

3.AOP切面编程实现登录拦截校验

首先目录结构如图所示

  • GlobalInterceptor类
java 复制代码
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface GlobalInterceptor {

    /**
     * 校验登录
     *
     * @return
     */
    boolean checkLogin() default true;

    /**
     * 校验管理员
     *
     * @return
     */
    boolean checkAdmin() default false;
}
  • GlobalOperationAspect类
java 复制代码
@Component("operationAspect")
@Aspect
public class GlobalOperationAspect {


    @Resource
    private RedisTemplate<String,String> redisTemplate;
    @Resource
    private UserMapper userMapper;

    private static Logger logger = LoggerFactory.getLogger(GlobalOperationAspect.class);


    @Before("@annotation(com.kkk.annotation.GlobalInterceptor)")
    public void interceptorDo(JoinPoint point) {
        try {
            Method method = ((MethodSignature) point.getSignature()).getMethod();
            GlobalInterceptor interceptor = method.getAnnotation(GlobalInterceptor.class);
            if (null == interceptor) {
                return;
            }
            /**
             * 校验登录
             */
            if (interceptor.checkLogin() || interceptor.checkAdmin()) {
                checkLogin(interceptor.checkAdmin());
            }
        } catch (BusinessException e) {
            logger.error("全局拦截器异常", e);
            throw e;
        } catch (Exception e) {
            logger.error("全局拦截器异常", e);
            throw new BusinessException(ResponseCodeEnum.CODE_500);
        } catch (Throwable e) {
            logger.error("全局拦截器异常", e);
            throw new BusinessException(ResponseCodeEnum.CODE_500);
        }
    }

    //校验登录
    private void checkLogin(Boolean checkAdmin) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader("token");
        String value = redisTemplate.opsForValue().get("loginDemo:user:token:"+token);
        if (value == null) {
            throw new BusinessException("登录超时");
        }
        Long userId = Long.valueOf(value);
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("请求参数错误,请联系管理员");
        }
        if (checkAdmin) {
            // 校验是否为管理员操作权限
            // 后续处理
        }
    }
}

接下来只需要在需要拦截的接口处添加自定义注解就可以了

如:

java 复制代码
@RestController
@RequestMapping("/test")
public class TestController {

    @GlobalInterceptor
    @GetMapping("/test")
    public String test() {
        return "ok";
    }
}

4. 测试

  • 首先登录后获取用户token

  • 再将token放入请求头中

一个AOP切面编程实现的登录拦截就实现了

相关推荐
rannn_1118 分钟前
【Git教程】概述、常用命令、Git-IDEA集成
java·git·后端·intellij-idea
我家领养了个白胖胖8 分钟前
向量化和向量数据库redisstack使用
java·后端·ai编程
苹果醋319 分钟前
Java设计模式实战:从面向对象原则到架构设计的最佳实践
java·运维·spring boot·mysql·nginx
郑州光合科技余经理29 分钟前
实战分享:如何构建东南亚高并发跑腿配送系统
java·开发语言·javascript·spring cloud·uni-app·c#·php
yaoxin52112334 分钟前
273. Java Stream API - Stream 中的中间操作:Mapping 操作详解
java·开发语言·python
一念一花一世界37 分钟前
Arbess从基础到实践(25) - 集成GitLab+阿里云OSS实现Java项目自动化构建并将制品上传Aliyun OSS
java·阿里云·gitlab·cicd·arbess
liyi_hz200839 分钟前
企业信创落地深水区:O2OA(翱途)平台的国产化适配实践与技术思考
java·开源软件
她说..42 分钟前
手机验证码功能实现(附带源码)
java·开发语言·spring boot·spring·java-ee·springboot
Adellle44 分钟前
Java-Stream流
java
fanruitian1 小时前
微信小程序 springboot获取手机号
spring boot·微信小程序·notepad++