java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot 登录拦截

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

作者:自律的kkk

本文介绍了如何使用AOP切面编程实现Spring Boot中的登录拦截,通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧

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

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

以下代码仅供参考

控制层

@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);
    }
}

业务层

@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层

@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 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类

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface GlobalInterceptor {
    /**
     * 校验登录
     *
     * @return
     */
    boolean checkLogin() default true;
    /**
     * 校验管理员
     *
     * @return
     */
    boolean checkAdmin() default false;
}

GlobalOperationAspect类

@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) {
            // 校验是否为管理员操作权限
            // 后续处理
        }
    }
}

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

如:

@RestController
@RequestMapping("/test")
public class TestController {
    @GlobalInterceptor
    @GetMapping("/test")
    public String test() {
        return "ok";
    }
}

4. 测试

首先登录后获取用户token

再将token放入请求头中

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

到此这篇关于SpringBoot中使用AOP切面编程实现登录拦截的文章就介绍到这了,更多相关SpringBoot 登录拦截内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文