使用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切面编程实现的登录拦截就实现了