여기에서는 주로 shiro의 사용자 정의 주석 솔루션을 채택합니다. 이 기사에서는 주로 다음과 같은 문제를 해결합니다.
로직을 통해 페이지를 API 인터페이스와 연결하는 방법.
Shiro의 자체 주석 사용.
맞춤 주석을 작성하는 방법.
테이블 간의 구조적 관계에서 페이지와 인터페이스 테이블은 궁극적으로 권한 테이블과 연결됩니다. (자세한 내용은 이전 기사 "권한" 디자인 토크"를 참조하세요.) .
이제는 어느 정도 권한 제어를 고려하면서 저렴한 비용을 달성할 수 있는 다른 솔루션으로 교체하기를 희망합니다. 여기서는 두 가지 개념을 소개합니다. 비즈니스 모듈, 운영 유형.
비즈니스 모듈
Concept: 시스템의 비즈니스 모듈을 문자열 형식으로 표현할 수 있는 일종의 데이터로 추상화합니다. 예를 들어 역할 관리는 역할 관리에 해당합니다. 사용자 관리는 사용자 관리 등에 해당합니다. '최소 권한의 원칙'을 통해 시스템에 존재하는 비즈니스 모듈을 분할하고 최종적으로 배포 가능한 데이터 배치를 구성합니다.
사용 원칙: API 인터페이스, 페이지 및 기능은 본질적으로 비즈니스 모듈과 논리적으로 관련되어 있습니다. 따라서 API 인터페이스와 페이지(및 기능 포인트)를 논리적으로 일치시켜 페이지가 일치하는지 확인할 수 있습니다. 비즈니스 모듈 관계.
Operation type
Concept: 시스템의 모든 작업 유형을 일종의 데이터로 추상화합니다. 예를 들어 새로운 추가는 추가 및 할당에 해당합니다. . 해당하는 것은 할당 등입니다. 비즈니스 모듈에 따라 "데이터 라이센스"를 통해 시스템의 모든 작업 유형을 나누고 최종적으로 배포 가능한 데이터 배치를 구성합니다.
사용 원칙: 페이지는 디스플레이, 기능 포인트는 액션, 인터페이스는 최종 액션을 위한 리소스 제공이며, 호출할 리소스는 "비즈니스 모듈"을 통해 결정됩니다. 리소스의 사용량은 "작업 유형"을 통해 결정됩니다. 두 가지를 통해 페이지의 기능 포인트에 의해 트리거된 인터페이스가 인증 범위 내에 있는지 대략적이고 정확하게 확인할 수 있습니다.
이제 이 두 가지 개념이 제안되었으니, 최종 실제 용도는 무엇인지 먼저 다음과 같은 관점에서 생각해 보겠습니다.
페이지 테이블이나 데이터베이스의 API 인터페이스 테이블에 있는 데이터가 실제이고 유효한가요?
페이지나 인터페이스의 실제 사용은 기능의 존재 여부 또는 데이터베이스 테이블의 데이터 존재 여부에 따라 결정됩니다.
권한 구조에서 "제어 개체"를 저장하는 유일한 방법은 데이터베이스입니까?
이러한 질문을 결론부터 살펴보겠습니다. 우선 "제어 개체"의 저장은 데이터베이스에 있을 수도 있고, 코드에 있을 수도 있고, 구성 파일에 있을 필요는 없습니다. ; 그런 다음 두 번째 질문에 답하십시오. 문제는 데이터베이스에 인터페이스 정보가 있지만 서버가 이 인터페이스를 개발하지 않은 경우 데이터베이스 정보 자체에 문제가 있거나 데이터베이스의 새 인터페이스가 다음과 같은 인터페이스를 가지고 있어야 한다는 것입니다. 적용하기 위해 서버에 배포되었습니다. 그런 다음 첫 번째 질문이 있습니다. 그러면 데이터베이스의 "제어 개체"에 대한 테이블의 데이터가 반드시 사실이고 유효한 것은 아닙니다. 그래서 우리는 다음과 같은 해결책을 생각해 낼 수 있습니다
"비즈니스 모듈"과 "작업 유형"의 데이터 정보를 보완하기 위해 인터페이스에서 주석을 사용할 수 있습니다. 두 가지 유형의 정보 모두 상수 클래스에 저장될 수 있습니다.
그러나 이 솔루션은 강력하지 않은 제어 인터페이스 프로젝트에만 적합합니다. 강력한 제어 인터페이스 프로젝트에서는 막대한 운영 및 유지 관리 비용이 발생하더라도 페이지와 인터페이스를 여전히 바인딩해야 합니다. 또한 인터페이스 라우팅 규칙으로 나눌 수도 있습니다. 예를 들어 /api/page/xxxx/(페이지에만 사용됨), /api/mobile/xxxxx(모바일 단말에만 사용됨)는 사용되는 인터페이스만 분류합니다. 이 클래스 인터페이스는 인증만 수행하지만 인증은 수행하지 않으며, 이는 목적을 달성할 수도 있습니다.
이론적인 아이디어를 승인한 후 나머지는 Apache를 사용하여 Spring에서 Shiro의 보안 프레임워크를 적용합니다. 부팅 환경. Shiro의 다음 주석을 간략하게 설명하십시오.
주석 이름 | 함수 |
---|---|
클래스, 메서드 및 인스턴스에 대해 작동합니다. 호출되면 현재 주체를 인증해야 합니다. | |
은 클래스, 메서드 및 인스턴스에 대해 작동합니다. 호출 시 주제는 게스트 상태일 수 있습니다. | |
은 클래스, 메서드 및 인스턴스에 대해 작동합니다. 호출 시 현재 인터페이스에서 프로젝트에 Permission(권한 정보)이 포함되어 있는지 확인해야 합니다. | |
은 클래스, 메서드 및 인스턴스에 대해 작동합니다. 호출 시 현재 인터페이스의 Role(역할 정보)이 주체에 포함되어 있는지 확인해야 합니다. | |
은 클래스, 메서드 및 인스턴스에 대해 작동합니다. 호출 시 주체가 현재 애플리케이션에 있는 사용자인지 여부를 확인해야 합니다. |
/** * 用于认证的接口的注解,组合形式默认是“或”的关系 */ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Auth { /** * 业务模块 * @return */ String[] module(); /** * 操作类型 */ String[] action(); }
/** * Auth注解的操作类 */ public class AuthHandler extends AuthorizingAnnotationHandler { public AuthHandler() { //写入注解 super(Auth.class); } @Override public void assertAuthorized(Annotation a) throws AuthorizationException { if (a instanceof Auth) { Auth annotation = (Auth) a; String[] module = annotation.module(); String[] action = annotation.action(); //1.获取当前主题 Subject subject = this.getSubject(); //2.验证是否包含当前接口的权限有一个通过则通过 boolean hasAtLeastOnePermission = false; for(String m:module){ for(String ac:action){ //使用hutool的字符串工具类 String permission = StrFormatter.format("{}:{}",m,ac); if(subject.isPermitted(permission)){ hasAtLeastOnePermission=true; break; } } } if(!hasAtLeastOnePermission){ throw new AuthorizationException("没有访问此接口的权限"); } } } }
/** * 拦截器 */ public class AuthMethodInterceptor extends AuthorizingAnnotationMethodInterceptor { public AuthMethodInterceptor() { super(new AuthHandler()); } public AuthMethodInterceptor(AnnotationResolver resolver) { super(new AuthHandler(), resolver); } @Override public void assertAuthorized(MethodInvocation mi) throws AuthorizationException { // 验证权限 try { ((AuthHandler) this.getHandler()).assertAuthorized(getAnnotation(mi)); } catch (AuthorizationException ae) { if (ae.getCause() == null) { ae.initCause(new AuthorizationException("当前的方法没有通过鉴权: " + mi.getMethod())); } throw ae; } } }
/** * shiro的aop切面 */ public class AuthAopInterceptor extends AopAllianceAnnotationsAuthorizingMethodInterceptor { public AuthAopInterceptor() { super(); // 添加自定义的注解拦截器 this.methodInterceptors.add(new AuthMethodInterceptor(new SpringAnnotationResolver())); } }
/** * 启动自定义注解 */ public class ShiroAdvisor extends AuthorizationAttributeSourceAdvisor { public ShiroAdvisor() { // 这里可以添加多个 setAdvice(new AuthAopInterceptor()); } @SuppressWarnings({"unchecked"}) @Override public boolean matches(Method method, Class targetClass) { Method m = method; if (targetClass != null) { try { m = targetClass.getMethod(m.getName(), m.getParameterTypes()); return this.isFrameAnnotation(m); } catch (NoSuchMethodException ignored) { } } return super.matches(method, targetClass); } private boolean isFrameAnnotation(Method method) { return null != AnnotationUtils.findAnnotation(method, Auth.class); } }
주석 클래스
(비즈니스에서 사용할 수 있는 변수 정의) -> 정의interceptor of Annotation->define aop's 관점 클래스->마지막으로 shiro의 사용자 정의 정의 주석 활성화 클래스 . 다른 사용자 정의 주석에 대한 작성 아이디어는 이와 유사합니다. 관련 권장사항: 사용자 정의 주석 매핑 thinkPHP21 사용자 정의 태그 라이브러리 가져오기 방법에 대한 자세한 설명# 🎜 🎜#Java의 사용자 정의 주석에 대한 자세한 소개shiro 인증 구현 세부 정보
위 내용은 shiro를 기반으로 한 사용자 정의 주석 확장 - 그림과 텍스트를 통한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!