当前位置: 首页 > wzjs >正文

宿迁网站搭建新手怎样做网络推广

宿迁网站搭建,新手怎样做网络推广,做网站的前期准备,全景网站建设本文通过自定义注解对 Controller 层的方法实现访问控制,其核心原理是基于 Spring AOP 的面向切面编程机制。系统在运行时由 Spring 生成目标类的动态代理对象,在方法执行前织入权限校验逻辑,从而实现对用户访问权限的统一拦截与验证&#xf…

本文通过自定义注解对 Controller 层的方法实现访问控制,其核心原理是基于 Spring AOP 的面向切面编程机制。系统在运行时由 Spring 生成目标类的动态代理对象,在方法执行前织入权限校验逻辑,从而实现对用户访问权限的统一拦截与验证,确保接口调用符合预设的安全规则。

package per.mjn.rbacdemo.common.security.annotation;public enum Logical
{/*** 必须具有所有的元素*/AND,/*** 只需具有其中一个元素*/OR
}
package per.mjn.rbacdemo.common.security.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 登录认证:只有登录之后才能进入该方法*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE})
public @interface RequiresLogin {}
package per.mjn.rbacdemo.common.security.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 权限认证:必须具有指定权限才能进入该方法*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface RequiresPermissions {/*** 需要校验的权限码*/String[] value() default {};/*** 验证模式:AND | OR, 默认AND*/Logical logical() default Logical.AND;
}
package per.mjn.rbacdemo.common.security.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 角色认证:必须具有指定角色标识才能进入该方法*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE })
public @interface RequiresRoles {/*** 需要校验的角色标识*/String[] value() default {};/*** 验证逻辑:AND | OR,默认AND*/Logical logical() default Logical.AND;
}

定义异常

package per.mjn.rbacdemo.common.exception;public class NotLoginException extends RuntimeException {public NotLoginException(String message) {super(message);}
}
package per.mjn.rbacdemo.common.exception;public class NotPermissionException extends RuntimeException {public NotPermissionException(String message) {super("无权限访问接口:" + message);}
}
package per.mjn.rbacdemo.common.exception;public class NotRoleException extends RuntimeException {public NotRoleException(String message) {super("缺少角色:" + message);}
}
package per.mjn.rbacdemo.common.security.aspect;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import per.mjn.rbacdemo.common.security.annotation.RequiresLogin;
import per.mjn.rbacdemo.common.security.annotation.RequiresPermissions;
import per.mjn.rbacdemo.common.security.annotation.RequiresRoles;
import per.mjn.rbacdemo.common.security.auth.AuthUtil;import java.lang.reflect.Method;/*** 基于 Spring Aop 的注解鉴权*/
@Aspect
@Component
public class PreAuthorizeAspect {/*** 构建*/public PreAuthorizeAspect() {}/*** 定义AOP签名 (切入所有使用鉴权注解的方法)*/public static final String POINTCUT_SIGN = " @annotation(per.mjn.rbacdemo.common.security.annotation.RequiresLogin) || "+ "@annotation(per.mjn.rbacdemo.common.security.annotation.RequiresPermissions) || "+ "@annotation(per.mjn.rbacdemo.common.security.annotation.RequiresRoles)";/*** 声明AOP签名*/@Pointcut(POINTCUT_SIGN)public void pointcut() {}/*** 环绕切入* * @param joinPoint 切面对象* @return 底层方法执行后的返回值* @throws Throwable 底层方法抛出的异常*/@Around("pointcut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {// 注解鉴权MethodSignature signature = (MethodSignature) joinPoint.getSignature();checkMethodAnnotation(signature.getMethod());try{// 执行原有逻辑Object obj = joinPoint.proceed();return obj;}catch (Throwable e){throw e;}}/*** 对一个Method对象进行注解检查*/public void checkMethodAnnotation(Method method) {// 校验 @RequiresLogin 注解RequiresLogin requiresLogin = method.getAnnotation(RequiresLogin.class);if (requiresLogin != null){AuthUtil.checkLogin();}// 校验 @RequiresRoles 注解RequiresRoles requiresRoles = method.getAnnotation(RequiresRoles.class);if (requiresRoles != null){AuthUtil.checkRole(requiresRoles);}// 校验 @RequiresPermissions 注解RequiresPermissions requiresPermissions = method.getAnnotation(RequiresPermissions.class);if (requiresPermissions != null){AuthUtil.checkPermi(requiresPermissions);}}
}
package per.mjn.rbacdemo.common.security.auth;import per.mjn.rbacdemo.common.exception.NotLoginException;
import per.mjn.rbacdemo.common.exception.NotPermissionException;
import per.mjn.rbacdemo.common.exception.NotRoleException;
import per.mjn.rbacdemo.common.security.annotation.Logical;
import per.mjn.rbacdemo.common.security.annotation.RequiresPermissions;
import per.mjn.rbacdemo.common.security.annotation.RequiresRoles;
import per.mjn.rbacdemo.common.security.context.LoginUserHolder;
import per.mjn.rbacdemo.domain.LoginUser;import java.util.List;public class AuthLogic {// 模拟登录用户(实际开发中从缓存或Token中获取)public LoginUser getLoginUser() {LoginUser user = LoginUserHolder.get();if (user == null) {throw new NotLoginException("用户未登录或token无效");}return user;}public LoginUser getLoginUser(String token) {return getLoginUser(); // 简化处理}public void checkLogin() {if (getLoginUser() == null) {throw new NotLoginException("未登录");}}public void checkRole(RequiresRoles requiresRoles) {String[] roles = requiresRoles.value();Logical logical = requiresRoles.logical();List<String> userRoles = getLoginUser().getRoles();if (logical == Logical.AND) {for (String role : roles) {if (!userRoles.contains(role)) {throw new NotRoleException(role);}}} else {for (String role : roles) {if (userRoles.contains(role)) return;}throw new NotRoleException(String.join(",", roles));}}public void checkPermi(RequiresPermissions requiresPermissions) {String[] perms = requiresPermissions.value();Logical logical = requiresPermissions.logical();List<String> userPerms = getLoginUser().getPermissions();if (logical == Logical.AND) {for (String perm : perms) {if (!userPerms.contains(perm)) {throw new NotPermissionException(perm);}}} else {for (String perm : perms) {if (userPerms.contains(perm)) return;}throw new NotPermissionException(String.join(",", perms));}}
}
package per.mjn.rbacdemo.common.security.auth;import per.mjn.rbacdemo.common.security.annotation.*;
import per.mjn.rbacdemo.domain.LoginUser;public class AuthUtil {public static AuthLogic authLogic = new AuthLogic();public static void checkLogin() {authLogic.checkLogin();}public static void checkRole(RequiresRoles requiresRoles) {authLogic.checkRole(requiresRoles);}public static void checkPermi(RequiresPermissions requiresPermissions) {authLogic.checkPermi(requiresPermissions);}public static LoginUser getLoginUser(String token) {return authLogic.getLoginUser(token);}
}
package per.mjn.rbacdemo.common.security.context;import per.mjn.rbacdemo.domain.LoginUser;public class LoginUserHolder {private static final ThreadLocal<LoginUser> userThreadLocal = new ThreadLocal<>();public static void set(LoginUser loginUser) {userThreadLocal.set(loginUser);}public static LoginUser get() {return userThreadLocal.get();}public static void clear() {userThreadLocal.remove();}
}

本文中的程序只是为了快速验证自定义注解能否起到权限控制的作用,并未连接数据库,所以,在请求拦截器中设计请求用户的信息(以代表当前请求的用户身份),同时为了便于测试,后期可直接在该部分修改用户信息。

package per.mjn.rbacdemo.common.security.interceptor;import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import per.mjn.rbacdemo.common.security.context.LoginUserHolder;
import per.mjn.rbacdemo.domain.LoginUser;import java.util.ArrayList;
import java.util.List;@Component
public class TokenInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {String token = request.getHeader("Authorization");// 实际应用中,token 应该解密+验签+查缓存等if (token != null && token.equals("mock-token")) {LoginUser loginUser = new LoginUser();loginUser.setUsername("testUser");List<String> roles = new ArrayList<>();roles.add("admin");List<String> permissions = new ArrayList<>();
//            permissions.add("system:user:query");permissions.add("system:user:create");loginUser.setRoles(roles);loginUser.setPermissions(permissions);LoginUserHolder.set(loginUser);}return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {LoginUserHolder.clear();}
}
package per.mjn.rbacdemo.common.web;import java.util.HashMap;public class AjaxResult extends HashMap<String, Object> {public static AjaxResult success(Object data) {AjaxResult result = new AjaxResult();result.put("code", 200);result.put("msg", "success");result.put("data", data);return result;}public static AjaxResult error(String msg) {AjaxResult result = new AjaxResult();result.put("code", 500);result.put("msg", msg);return result;}
}
package per.mjn.rbacdemo.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;
import per.mjn.rbacdemo.common.security.interceptor.TokenInterceptor;@Configuration
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate TokenInterceptor tokenInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(tokenInterceptor).addPathPatterns("/**");}
}
package per.mjn.rbacdemo.controller;import org.springframework.web.bind.annotation.*;
import per.mjn.rbacdemo.common.security.annotation.*;
import per.mjn.rbacdemo.common.security.annotation.Logical;
import per.mjn.rbacdemo.common.web.AjaxResult;
import per.mjn.rbacdemo.domain.LoginUser;import java.util.List;@RestController
@RequestMapping("/user")
public class UserController {@RequiresLogin@GetMapping("/profile")public AjaxResult getProfile() {return AjaxResult.success("用户信息");}@RequiresPermissions("system:user:query")@GetMapping("/{userId}")public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) {return AjaxResult.success("查询用户: " + (userId != null ? userId : "全部"));}@RequiresRoles(value = {"admin", "manager"}, logical = Logical.OR)@PostMapping("/create")public AjaxResult createUser() {LoginUser user = new LoginUser();user.setUsername("admin");user.setRoles(List.of("admin", "user"));user.setPermissions(List.of("system:user:query", "system:user:create"));return AjaxResult.success("创建成功");}
}
package per.mjn.rbacdemo.domain;import java.util.List;
import java.util.Set;
import lombok.Data;@Data
public class LoginUser {private String username;private List<String> roles;private List<String> permissions;
}
package per.mjn.rbacdemo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class RbacDemoApplication {public static void main(String[] args) {SpringApplication.run(RbacDemoApplication.class, args);}}

测试自定义权限控制注解

(1)访问时未携带Token
在这里插入图片描述
在这里插入图片描述

(2)访问时携带Token,但没有该接口的访问权限

在这里插入图片描述
在这里插入图片描述

(3)访问时携带Token,且拥有该接口的访问权限

此时,需要将TokenInterceptor类中preHandle()方法中的注释去掉

permissions.add("system:user:query");

在这里插入图片描述


附:pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.5.0</version><relativePath/></parent><modelVersion>4.0.0</modelVersion><groupId>per.mjn</groupId><artifactId>RBACDemo</artifactId><version>0.0.1-SNAPSHOT</version><name>RBACDemo</name><description>RBACDemo</description><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><scope>test</scope></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId></dependency><!-- redis依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- lombok 依赖 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!-- MyBatis 依赖 --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.3</version></dependency><!-- MySQL 依赖 --><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><!-- Java Servlet --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version></dependency><!-- Jwt --><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

项目结构目录

在这里插入图片描述

http://www.dtcms.com/wzjs/406354.html

相关文章:

  • 平面设计大赛网站好用的网站推荐
  • 网罗设计网站现在的网络推广怎么做
  • 网站建设推广入什么费用福州网站建设团队
  • 地方门户网站运营四川seo多少钱
  • 北京网站建设公司新闻长沙优化官网服务
  • 什么网站可以做电影投资河南网站推广电话
  • 怀化公积金网站站长工具seo综合查询源码
  • 汕头智能模板建站拓客最有效方案
  • 免费做app的网站哪个好河南靠谱seo地址
  • 有了域名 网站建设腾讯企点官网
  • 德宏网站建设公司免费网站优化排名
  • 网站建设电话销售技巧成都达洱狐网络科技有限公司
  • 九宫格导航网站网络推广免费网站
  • 成都网站建设潮州宣传渠道有哪些
  • 做设计网站的工作怎么样的广州网络营销推广
  • 图片直链在线生成网站品牌推广方案范文
  • 广州网站建设设计怎么在百度上做网站
  • 中国建筑工程机械网东莞百度seo关键词优化
  • 护肤品网站建设策划书百度网盘搜索引擎入口官网
  • asp网站如何安装网站设计的毕业论文
  • 外贸小网站建设网站一般需要怎么推广
  • 电子商务书城网站建设方案百度提升排名
  • 八桂云网站建设湖北百度关键词排名软件
  • 网站流量统计工具中文网站排名
  • 网站策划方案如何做谷歌seo搜索引擎优化
  • 做日签的网站北京全网推广
  • 手机网站开发步骤万网域名注册官网
  • 网站空间租赁友情链接交换教程
  • 加大网站集约化建设管理信息发布平台推广有哪些
  • 选择邯郸网站制作郑州网站建设七彩科技