SpringBoot中使用AOP切面編程實(shí)現(xiàn)登錄攔截功能
使用AOP切面編程實(shí)現(xiàn)登錄攔截
1. 首先實(shí)現(xiàn)一個(gè)登錄注冊(cè)功能
以下代碼僅供參考
控制層
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/register")
public Result register(@RequestBody UserDto userDto) {
userService.addUser(userDto);
return Result.success("注冊(cè)成功");
}
@PostMapping("/login")
public Result<UserLoginVo> login(@RequestBody UserDto userDto) {
UserLoginVo userLoginVo = userService.login(userDto);
return Result.success(userLoginVo);
}
}業(yè)務(wù)層
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Resource
private RedisTemplate<String,String> redisTemplate;
/**
* 新增用戶/注冊(cè)
* @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("用戶名或密碼錯(cuò)誤");
}
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>以上代碼僅供參考,具體邏輯可以根據(jù)自己的業(yè)務(wù)來實(shí)現(xiàn)
2. 補(bǔ)充介紹
以上提供的示例代碼邏輯大致為用戶登錄后根據(jù)UUID生成一個(gè)token,接著將token作為唯一標(biāo)識(shí)鍵存入redis緩存中,值為用戶id,之后可以根據(jù)用戶請(qǐng)求頭中的token去redis中獲取用戶id,當(dāng)然你也可以根據(jù)自己的實(shí)際需求來。
3.AOP切面編程實(shí)現(xiàn)登錄攔截校驗(yàn)

首先目錄結(jié)構(gòu)如圖所示
GlobalInterceptor類
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface GlobalInterceptor {
/**
* 校驗(yàn)登錄
*
* @return
*/
boolean checkLogin() default true;
/**
* 校驗(yàn)管理員
*
* @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;
}
/**
* 校驗(yàn)登錄
*/
if (interceptor.checkLogin() || interceptor.checkAdmin()) {
checkLogin(interceptor.checkAdmin());
}
} catch (BusinessException e) {
logger.error("全局?jǐn)r截器異常", e);
throw e;
} catch (Exception e) {
logger.error("全局?jǐn)r截器異常", e);
throw new BusinessException(ResponseCodeEnum.CODE_500);
} catch (Throwable e) {
logger.error("全局?jǐn)r截器異常", e);
throw new BusinessException(ResponseCodeEnum.CODE_500);
}
}
//校驗(yàn)登錄
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("登錄超時(shí)");
}
Long userId = Long.valueOf(value);
User user = userMapper.selectById(userId);
if (user == null) {
throw new BusinessException("請(qǐng)求參數(shù)錯(cuò)誤,請(qǐng)聯(lián)系管理員");
}
if (checkAdmin) {
// 校驗(yàn)是否為管理員操作權(quán)限
// 后續(xù)處理
}
}
}接下來只需要在需要攔截的接口處添加自定義注解就可以了
如:
@RestController
@RequestMapping("/test")
public class TestController {
@GlobalInterceptor
@GetMapping("/test")
public String test() {
return "ok";
}
}4. 測試
首先登錄后獲取用戶token

再將token放入請(qǐng)求頭中

一個(gè)AOP切面編程實(shí)現(xiàn)的登錄攔截就實(shí)現(xiàn)了
到此這篇關(guān)于SpringBoot中使用AOP切面編程實(shí)現(xiàn)登錄攔截的文章就介紹到這了,更多相關(guān)SpringBoot 登錄攔截內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Cloud Toolkit在IDEA中極速創(chuàng)建dubbo工程
這篇文章主要介紹了使用Cloud Toolkit在IDEA中極速創(chuàng)建dubbo工程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
springboot使用@ConfigurationProperties實(shí)現(xiàn)自動(dòng)綁定配置參數(shù)屬性
這篇文章主要介紹了springboot使用@ConfigurationProperties實(shí)現(xiàn)自動(dòng)綁定配置參數(shù)屬性,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-05-05
Spring中@Configuration和@Component注解的區(qū)別及原理
這篇文章主要介紹了Spring中@Configuration和@Component注解的區(qū)別及原理,從功能上來講,這些注解所負(fù)責(zé)的功能的確不相同,但是從本質(zhì)上來講,Spring內(nèi)部都將其作為配置注解進(jìn)行處理,需要的朋友可以參考下2023-11-11
手把手帶你分析SpringBoot自動(dòng)裝配完成了Ribbon哪些核心操作
這篇文章主要介紹了詳解Spring Boot自動(dòng)裝配Ribbon哪些核心操作的哪些操作,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-08-08
舉例分析Python中設(shè)計(jì)模式之外觀模式的運(yùn)用
這篇文章主要介紹了Python中設(shè)計(jì)模式之外觀模式的運(yùn)用,外觀模式主張以分多模塊進(jìn)行代碼管理而減少耦合,需要的朋友可以參考下2016-03-03
Mybatis-Plus saveBatch()批量保存失效的解決
本文主要介紹了Mybatis-Plus saveBatch()批量保存失效的解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01
java 中List按照date排序的實(shí)現(xiàn)
這篇文章主要介紹了java 中List按照date排序的實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2017-06-06
Java開發(fā)實(shí)現(xiàn)人機(jī)猜拳游戲
這篇文章主要為大家詳細(xì)介紹了Java開發(fā)實(shí)現(xiàn)人機(jī)猜拳游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08

