SpringBoot中使用AOP切面編程實現(xiàn)登錄攔截功能
使用AOP切面編程實現(xiàn)登錄攔截
1. 首先實現(xiàn)一個登錄注冊功能
以下代碼僅供參考
控制層
@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); } }
業(yè)務(wù)層
@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>
以上代碼僅供參考,具體邏輯可以根據(jù)自己的業(yè)務(wù)來實現(xiàn)
2. 補充介紹
以上提供的示例代碼邏輯大致為用戶登錄后根據(jù)UUID生成一個token,接著將token作為唯一標識鍵存入redis緩存中,值為用戶id,之后可以根據(jù)用戶請求頭中的token去redis中獲取用戶id,當然你也可以根據(jù)自己的實際需求來。
3.AOP切面編程實現(xiàn)登錄攔截校驗
首先目錄結(jié)構(gòu)如圖所示
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("請求參數(shù)錯誤,請聯(lián)系管理員"); } if (checkAdmin) { // 校驗是否為管理員操作權(quán)限 // 后續(xù)處理 } } }
接下來只需要在需要攔截的接口處添加自定義注解就可以了
如:
@RestController @RequestMapping("/test") public class TestController { @GlobalInterceptor @GetMapping("/test") public String test() { return "ok"; } }
4. 測試
首先登錄后獲取用戶token
再將token放入請求頭中
一個AOP切面編程實現(xiàn)的登錄攔截就實現(xiàn)了
到此這篇關(guān)于SpringBoot中使用AOP切面編程實現(xiàn)登錄攔截的文章就介紹到這了,更多相關(guān)SpringBoot 登錄攔截內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java數(shù)據(jù)結(jié)構(gòu)與算法學習之循環(huán)鏈表
循環(huán)鏈表是另一種形式的鏈式存儲結(jié)構(gòu)。它的特點是表中最后一個結(jié)點的指針域指向頭結(jié)點,整個鏈表形成一個環(huán)。本文將為大家詳細介紹一下循環(huán)鏈表的特點與使用,需要的可以了解一下2021-12-12Netty4之如何實現(xiàn)HTTP請求、響應(yīng)
這篇文章主要介紹了Netty4之如何實現(xiàn)HTTP請求、響應(yīng)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04詳解springmvc控制登錄用戶session失效后跳轉(zhuǎn)登錄頁面
本篇文章主要介紹了springmvc控制登錄用戶session失效后跳轉(zhuǎn)登錄頁面,session一旦失效就需要重新登陸,有興趣的同學可以了解一下。2017-01-01