JavaRush /Java Blog /Random-KO /JAAS - 기술 소개(1부)
Viacheslav
레벨 3

JAAS - 기술 소개(1부)

Random-KO 그룹에 게시되었습니다
액세스 보안은 오랫동안 Java로 구현되어 왔으며 이 보안을 제공하는 아키텍처를 JAAS(Java Authentication and Authorization Service)라고 합니다. 이 리뷰에서는 인증, 권한 부여가 무엇인지, 그리고 JAAS가 그것과 어떤 관련이 있는지에 대한 수수께끼를 풀려고 노력할 것입니다. JAAS가 Servlet API와 친구가 되는 방법과 관계에서 문제가 있는 부분.
JAAS - 기술 소개(1부) - 1

소개

이번 리뷰에서는 웹 애플리케이션 보안과 같은 주제에 대해 논의하고 싶습니다. Java에는 보안을 제공하는 여러 기술이 있습니다. 하지만 오늘 우리의 대화는 "JAAS(Java Authentication and Authorization Service)"라는 또 다른 기술에 관한 것입니다. 인증 및 권한 부여와 같은 중요한 사항을 설명하는 것은 바로 그녀입니다. 이를 좀 더 자세히 살펴보겠습니다.
JAAS - 기술 소개(1부) - 2

JAAS

JAAS 는 Java SE의 확장이며 JAAS(Java Authentication and Authorization Service) 참조 가이드 에 설명되어 있습니다 . 기술 이름에서 알 수 있듯이 JAAS는 인증 및 권한 부여가 수행되는 방법을 설명합니다.
  • " 인증 ": 그리스어로 번역된 "authentikos"는 "진짜, 진짜"를 의미합니다. 즉, 인증은 진위 여부를 테스트하는 것입니다. 인증을 받는 사람이 바로 자신이 말하는 사람입니다.

  • " 승인 ": 영어로 번역되면 "허가"를 의미합니다. 즉, 권한 부여는 인증 성공 후 수행되는 접근 제어입니다.

즉, JAAS는 리소스에 대한 액세스를 요청하는 사람이 누구인지 결정하고 그가 이 액세스 권한을 얻을 수 있는지 여부를 결정하는 것입니다. 인생에 대한 작은 비유: 당신이 길을 따라 운전하고 있는데 검사관이 당신을 멈춥니다. 서류를 제출해주세요 - 인증. 서류를 가지고 차를 운전할 수 있습니까? 또는 예를 들어 상점에서 술을 사고 싶습니다. 먼저 여권 인증을 요청합니다. 다음으로, 나이에 따라 술을 구입할 수 있는지 여부가 결정됩니다. 이것이 승인입니다. 웹 애플리케이션에서는 사용자로 로그인(사용자 이름과 비밀번호 입력)하는 것이 인증입니다. 열 수 있는 페이지를 결정하는 것은 인증에 따라 결정됩니다. 이것이 바로 "JAAS(Java Authentication and Authorization Service)"가 우리를 도와주는 곳입니다. JAAS를 고려할 때 JAAS가 설명하는 몇 가지 주요 개념인 주제, 주체, 자격 증명을 이해하는 것이 중요합니다. Subject 는 인증 대상입니다. 즉, 권리의 소유자 또는 보유자입니다. 문서에서 제목은 일부 작업을 수행하라는 요청의 소스로 정의됩니다. 주제나 출처는 어떻게든 설명되어야 하며 이를 위해 러시아어에서는 때때로 Principal이라고도 불리는 Principal이 사용됩니다. 즉, 각 주체는 특정 관점에서 주체를 표현한 것입니다. 더 명확하게 하기 위해 예를 들어 보겠습니다. 특정 사람이 주체입니다. 다음은 주체 역할을 할 수 있습니다.
  • 도로 사용자로서의 사람을 나타내는 운전 면허증
  • 그의 여권은 그의 나라의 시민으로서의 사람을 대표합니다.
  • 국제 관계에 참여하는 사람을 대표하는 외국 여권
  • 도서관에 있는 자신의 도서관 카드(도서관에 부착된 독자로서의 사람을 나타냄)
또한, Subject에는 영어로 "identity"를 의미하는 "Credential"이라는 집합이 있습니다. 이것이 주체가 자신임을 확인하는 방법입니다. 예를 들어, 사용자의 비밀번호는 Credential일 수 있습니다. 또는 사용자가 자신이 실제로 그 사람인지 확인할 수 있는 모든 개체입니다. 이제 웹 애플리케이션에서 JAAS가 어떻게 사용되는지 살펴보겠습니다.
JAAS - 기술 소개(1부) - 3

웹 애플리케이션

따라서 웹 애플리케이션이 필요합니다. Gradle 자동 프로젝트 빌드 시스템이 이를 생성하는 데 도움이 될 것입니다. Gradle을 사용하면 작은 명령을 실행하여 필요한 형식으로 Java 프로젝트를 어셈블하고 필요한 디렉토리 구조를 자동으로 생성하는 등의 작업을 수행할 수 있습니다. 간단한 개요: " Gradle에 대한 간략한 소개 " 또는 공식 문서 " Gradle 시작하기 "에서 Gradle에 대해 자세히 알아볼 수 있습니다. 프로젝트를 초기화(Initialization)해야 하며, 이를 위해 Gradle에는 " Gradle Init Plugin "이라는 특수 플러그인이 있습니다(Init는 초기화의 약어이며 기억하기 쉽습니다). 이 플러그인을 사용하려면 명령줄에서 다음 명령을 실행하세요.
gradle init --type java-application
성공적으로 완료되면 Java 프로젝트가 생성됩니다. 이제 편집을 위해 프로젝트의 빌드 스크립트를 열어 보겠습니다. build.gradle빌드 스크립트는 애플리케이션 빌드의 미묘한 차이를 설명 하는 파일입니다 . 따라서 이름, 빌드 스크립트. 이것이 프로젝트 빌드 스크립트라고 말할 수 있습니다. Gradle은 플러그인을 통해 기본 기능이 확장되는 다재다능한 도구입니다. 그러므로 우선 "플러그인" 블록에 주목해 봅시다:
plugins {
    id 'java'
    id 'application'
}
기본적으로 Gradle은 우리가 지정한 " "에 따라 --type java-application일부 핵심 플러그인 세트, 즉 Gradle 자체 배포에 포함된 플러그인을 설정했습니다. gradle.org 웹사이트 의 "Docs"(즉, 설명서) 섹션 으로 이동하면 "참조" 섹션의 항목 목록 왼쪽에 " Core Plugins " 섹션이 표시됩니다. 매우 기본적인 플러그인에 대한 설명이 포함된 섹션입니다. Gradle이 생성한 플러그인이 아닌 우리에게 필요한 플러그인을 정확하게 선택해 보겠습니다. 문서에 따르면 " Gradle Java Plugin "은 소스 코드 컴파일과 같은 Java 코드와 함께 기본 작업을 제공합니다. 또한 문서에 따르면 " Gradle 애플리케이션 플러그인 "은 "실행 가능한 JVM 애플리케이션" 작업을 위한 도구를 제공합니다. 독립 실행형 애플리케이션(예: 콘솔 애플리케이션 또는 자체 UI가 있는 애플리케이션)으로 시작할 수 있는 Java 애플리케이션을 사용합니다. "application" 플러그인이 필요하지 않다는 것이 밝혀졌습니다. 왜냐하면... 독립형 앱이 아니라 웹 앱이 필요합니다. 삭제해 보겠습니다. 이 플러그인에만 알려진 "mainClassName" 설정도 마찬가지입니다. 또한 애플리케이션 플러그인 문서에 대한 링크가 제공된 동일한 " 패키징 및 배포 " 섹션에 Gradle War 플러그인에 대한 링크가 있습니다. 문서에 명시된 대로 Gradle War 플러그인은 war 형식으로 Java 웹 애플리케이션을 생성하기 위한 지원을 제공합니다. WAR 형식에서는 JAR 아카이브 대신 WAR 아카이브가 생성된다는 의미입니다. 이것이 우리에게 필요한 것 같습니다. 또한 문서에 따르면 "War 플러그인은 Java 플러그인을 확장합니다." 즉, java 플러그인을 war 플러그인으로 대체할 수 있습니다. 따라서 우리의 플러그인 블록은 궁극적으로 다음과 같습니다:
plugins {
    id 'war'
}
또한 "Gradle War 플러그인"에 대한 문서에는 플러그인이 추가 "프로젝트 레이아웃"을 사용한다고 나와 있습니다. 레이아웃은 영어에서 위치로 번역됩니다. 즉, war 플러그인은 기본적으로 해당 작업에 사용할 특정 파일 위치가 있을 것으로 예상합니다. 웹 애플리케이션 파일을 저장하기 위해 다음 디렉토리를 사용합니다. src/main/webapp 플러그인의 동작은 다음과 같습니다.
JAAS - 기술 소개(1부) - 4
즉, 플러그인은 웹 애플리케이션의 WAR 아카이브를 구축할 때 이 위치의 파일을 고려합니다. 또한 Gradle War 플러그인 문서에는 이 디렉터리가 "아카이브의 루트"가 될 것이라고 나와 있습니다. 그리고 이미 그 안에 WEB-INF 디렉토리를 생성하고 거기에 web.xml 파일을 추가할 수 있습니다. 이것은 어떤 종류의 파일입니까? web.xml- 이는 "배포 설명자" 또는 "배포 설명자"입니다. 이는 웹 애플리케이션이 작동하도록 구성하는 방법을 설명하는 파일입니다. 이 파일은 애플리케이션이 처리할 요청, 보안 설정 등을 지정합니다. 핵심은 JAR 파일의 매니페스트 파일과 다소 유사합니다(" 매니페스트 파일 작업: 기본 사항 " 참조). 매니페스트 파일은 Java 애플리케이션(예: JAR 아카이브)으로 작업하는 방법을 알려주고 web.xml은 Java 웹 애플리케이션(예: WAR 아카이브)으로 작업하는 방법을 알려줍니다. "배포 설명자"라는 개념 자체는 자체적으로 발생하지 않았지만 " 서블릿 API 사양" 문서에 설명되어 있습니다.". 모든 Java 웹 애플리케이션은 이 "서블릿 API"에 의존합니다. 이것이 API라는 것을 이해하는 것이 중요합니다. 즉, 일부 상호 작용 계약에 대한 설명입니다. 웹 애플리케이션은 독립적인 애플리케이션이 아닙니다. 웹 서버에서 실행됩니다. , 사용자와의 네트워크 통신을 제공합니다. 즉, 웹 서버는 웹 애플리케이션을 위한 일종의 "컨테이너"입니다. 이는 웹 애플리케이션의 논리, 즉 사용자가 볼 페이지와 방법을 작성하기를 원하기 때문에 논리적입니다. 그들은 사용자의 행동에 반응해야 합니다. 그리고 우리는 메시지가 사용자에게 전송되는 방법, 정보 바이트가 전송되는 방법 및 기타 낮은 수준의 매우 품질을 요구하는 사항에 대한 코드를 작성하고 싶지 않습니다. 웹 애플리케이션은 모두 다르지만 데이터 전송은 동일합니다. 즉, 백만 명의 프로그래머가 동일한 목적을 위해 계속해서 코드를 작성해야 합니다. 따라서 웹 서버는 사용자 상호 작용의 일부를 담당합니다. 데이터 교환 및 웹 애플리케이션과 개발자는 해당 데이터를 생성할 책임이 있습니다. 그리고 이 두 부분을 연결하기 위해, 즉 웹 서버와 웹 애플리케이션의 상호 작용을 위해서는 계약이 필요합니다. 이를 위해 그들은 어떤 규칙을 따를 것인가? 웹 애플리케이션과 웹 서버 간의 상호 작용이 어떤 모습이어야 하는지, 계약을 어떻게든 설명하기 위해 Servlet API가 발명되었습니다. 흥미롭게도 Spring과 같은 프레임워크를 사용하더라도 내부적으로는 여전히 Servlet API가 실행됩니다. 즉, 당신은 Spring을 사용하고 Spring은 당신을 위해 Servlet API와 함께 작동합니다. 우리의 웹 애플리케이션 프로젝트는 Servlet API에 의존해야 한다는 것이 밝혀졌습니다. 이 경우 Servlet API는 종속성이 됩니다. 우리가 알고 있듯이 Gradle을 사용하면 선언적인 방식으로 프로젝트 종속성을 설명할 수도 있습니다. 플러그인은 종속성을 관리하는 방법을 설명합니다. 예를 들어, Java Gradle 플러그인은 이러한 종속성이 테스트에만 필요함을 나타내는 "testImplementation" 종속성 관리 방법을 도입합니다. 그러나 Gradle War 플러그인은 종속성 관리 방법인 "providedCompile"을 추가합니다. 이는 이러한 종속성이 웹 애플리케이션의 WAR 아카이브에 포함되지 않음을 의미합니다. WAR 아카이브에 Servlet API를 포함시키면 어떨까요? Servlet API는 웹 서버 자체에서 웹 애플리케이션에 제공되기 때문입니다. 웹 서버가 서블릿 API를 제공하는 경우 서버를 서블릿 컨테이너라고 합니다. 그러므로 우리에게 Servlet API를 제공하는 것은 웹 서버의 책임이고, 코드가 컴파일되는 시점에만 ServletAPI를 제공하는 것은 우리의 책임입니다. 그렇기 때문에 providedCompile. 따라서 종속성 블록은 다음과 같습니다.
dependencies {
    providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
    testImplementation 'junit:junit:4.12'
}
이제 web.xml 파일로 돌아가 보겠습니다. 기본적으로 Gradle은 배포 설명자를 생성하지 않으므로 이 작업을 직접 수행해야 합니다. 디렉토리를 생성 src/main/webapp/WEB-INF하고 그 안에 이라는 XML 파일을 생성하겠습니다 web.xml. 이제 "Java Servlet 사양" 자체와 " 14장 배포 설명자 " 장을 열어 보겠습니다 . "14.3 배포 설명자"에 설명된 대로 배포 설명자의 XML 문서는 http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd 스키마로 설명됩니다 . XML 스키마는 문서가 어떤 요소로 구성될 수 있는지, 그리고 해당 요소가 어떤 순서로 표시되어야 하는지를 설명합니다. 필수 사항과 그렇지 않은 사항. 일반적으로 문서의 구조를 설명하며, XML 문서가 올바르게 구성되었는지 확인할 수 있습니다. 이제 " 14.5 예제 " 장의 예제를 사용하겠습니다 . 하지만 버전 3.1에 대해 구성표를 지정해야 합니다.
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd
우리의 빈 것은 web.xml다음과 같습니다:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <display-name>JAAS Example</display-name>
</web-app>
이제 JAAS를 사용하여 보호할 서블릿에 대해 설명하겠습니다. 이전에는 Gradle이 App 클래스를 생성했습니다. 이를 서블릿으로 바꿔보자. " 제2장 서블릿 인터페이스 " 의 사양에 명시된 대로 " 대부분의 목적을 위해 개발자는 HttpServlet을 확장하여 서블릿을 구현합니다. " 즉, 클래스를 서블릿으로 만들려면 다음에서 이 클래스를 상속해야 합니다 HttpServlet.
public class App extends HttpServlet {
	public String getGreeting() {
        return "Secret!";
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().print(getGreeting());
    }
}
앞서 말했듯이 Servlet API는 서버와 웹 애플리케이션 간의 계약입니다. 이 계약을 통해 사용자가 서버에 접속하면 서버가 사용자로부터 객체 형태로 요청을 생성하여 HttpServletRequest서블릿에 전달한다는 점을 설명할 수 있습니다. HttpServletResponse또한 서블릿이 사용자를 위해 응답을 작성할 수 있도록 서블릿 에 개체를 제공합니다 . 서블릿의 실행이 완료되면 서버는 이를 기반으로 사용자에게 응답을 제공할 수 있습니다 HttpServletResponse. 즉, 서블릿은 사용자와 직접 통신하지 않고 서버와만 통신합니다. 서버가 서블릿이 있고 어떤 요청에 사용해야 하는지 알 수 있도록 배포 설명자에서 이에 대해 서버에 알려야 합니다.
<servlet>
	<servlet-name>app</servlet-name>
	<servlet-class>jaas.App</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>app</servlet-name>
	<url-pattern>/secret</url-pattern>
</servlet-mapping>
이 경우 모든 요청은 클래스에 해당하는 /secret이름으로 하나의 서블릿으로 전달되지 않습니다 . 앞서 말했듯이 웹 애플리케이션은 웹 서버에만 배포할 수 있습니다. 웹 서버는 별도로(독립형) 설치할 수 있습니다. 그러나 이 검토의 목적에 따라 내장형 서버에서 실행되는 대체 옵션이 적합합니다. 이는 서버가 프로그래밍 방식으로 생성 및 시작되고(플러그인이 이 작업을 수행함) 동시에 웹 애플리케이션이 해당 서버에 배포된다는 의미입니다. Gradle 빌드 시스템을 사용하면 다음과 같은 목적으로 " Gradle Gretty 플러그인 " 플러그인을 사용할 수 있습니다 .appjaas.App
plugins {
    id 'war'
    id 'org.gretty' version '2.2.0'
}
또한 Gretty 플러그인에는 좋은 문서가 있습니다 . Gretty 플러그인을 사용하면 여러 웹 서버 간에 전환할 수 있다는 사실부터 시작해 보겠습니다. 이에 대한 자세한 내용은 " 서블릿 컨테이너 간 전환 " 문서에 설명되어 있습니다 . Tomcat으로 전환합시다. 왜냐면... 이는 가장 널리 사용되는 것 중 하나이며, 좋은 문서와 많은 예제 및 분석된 문제도 포함하고 있습니다.
gretty {
    // Переключаемся с дефолтного Jetty на Tomcat
    servletContainer = 'tomcat8'
    // Укажем Context Path, он же Context Root
    contextPath = '/jaas'
}
이제 "gradle appRun"을 실행할 수 있으며 그러면 웹 애플리케이션을 http://localhost:8080/jaas/secret에서 사용할 수 있습니다.
JAAS - 기술 소개(1부) - 5
Tomcat이 서블릿 컨테이너를 선택했는지 확인하고(#1 참조) 웹 애플리케이션을 사용할 수 있는 주소를 확인하는 것이 중요합니다(#2 참조).
JAAS - 기술 소개(1부) - 6

입증

인증 설정은 대개 서버 측 설정과 이 서버에서 실행되는 웹 애플리케이션 측 설정의 두 부분으로 구성됩니다. 웹 애플리케이션이 웹 서버와 상호 작용할 수 밖에 없는 다른 이유가 없다면 웹 애플리케이션의 보안 설정은 웹 서버의 보안 설정과 상호 작용할 수밖에 없습니다. 우리가 Tomcat으로 전환한 것은 헛되지 않았습니다. 왜냐하면... Tomcat에는 잘 설명된 아키텍처가 있습니다(" Apache Tomcat 8 아키텍처 " 참조). 이 아키텍처에 대한 설명을 보면 웹 서버인 Tomcat이 웹 애플리케이션을 " Tomcat 컨텍스트 " 라고 하는 특정 컨텍스트로 표현한다는 것이 분명합니다 . 이 컨텍스트를 통해 각 웹 애플리케이션은 다른 웹 애플리케이션과 격리된 자체 설정을 가질 수 있습니다. 또한 웹 애플리케이션은 이 컨텍스트의 설정에 영향을 미칠 수 있습니다. 유연하고 편리합니다. 더 깊이 이해하려면 " Tomcat 컨텍스트 컨테이너 이해 " 문서 와 Tomcat 문서 섹션 " 컨텍스트 컨테이너 "를 읽어보는 것이 좋습니다. 위에서 설명한 대로 웹 애플리케이션은 /META-INF/context.xml. 우리가 영향을 미칠 수 있는 매우 중요한 설정 중 하나는 보안 영역입니다. 보안 영역은 일종의 "보안 영역"입니다. 특정 보안 설정이 지정되는 영역입니다. 따라서 보안 영역을 사용할 때 이 영역에 대해 정의된 보안 설정을 적용합니다. 보안 영역은 컨테이너에 의해 관리됩니다. 웹 애플리케이션이 아닌 웹 서버입니다. 애플리케이션으로 확장해야 하는 보안 범위만 서버에 알릴 수 있습니다. " The Realm Component " 섹션의 Tomcat 문서에서는 Realm을 사용자와 인증 수행을 위한 역할에 대한 데이터 모음으로 설명합니다. Tomcat은 " Jaas Realm " 중 하나인 다양한 보안 영역 구현 세트를 제공합니다 . 약간의 용어를 이해한 후 파일에서 Tomcat 컨텍스트를 설명하겠습니다 /META-INF/context.xml.
<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <Realm className="org.apache.catalina.realm.JAASRealm"
           appName="JaasLogin"
           userClassNames="jaas.login.UserPrincipal"
           roleClassNames="jaas.login.RolePrincipal"
           configFile="jaas.config" />
</Context>
appName— 애플리케이션 이름. Tomcat은 이 이름을 configFile. configFile- 이것은 "로그인 구성 파일"입니다. 이에 대한 예는 JAAS 문서 " 부록 B: 로그인 구성 예 "에서 볼 수 있습니다. 또한 이 파일이 리소스에서 먼저 검색되는 것이 중요합니다. 따라서 우리 웹 애플리케이션은 이 파일 자체를 제공할 수 있습니다. 사용자의 주체를 나타내는 클래스에 대한 표시를 포함하는 속성 userClassNames입니다 . roleClassNamesJAAS는 "사용자"와 "역할"의 개념을 두 가지 다른 개념으로 분리합니다 java.security.Principal. 위의 클래스에 대해 설명하겠습니다. 사용자 주체에 대한 가장 간단한 구현을 만들어 보겠습니다.
public class UserPrincipal implements Principal {
    private String name;
    public UserPrincipal(String name) {
        this.name = name;
    }
    @Override
    public String getName() {
        return name;
    }
}
에 대해 정확히 동일한 구현을 반복합니다 RolePrincipal. 인터페이스에서 볼 수 있듯이 Principal의 주요 작업은 Principal을 나타내는 일부 이름(또는 ID)을 저장하고 반환하는 것입니다. 이제 보안 영역과 주요 클래스가 있습니다. configFile" " 속성(일명 ) 에서 파일을 채우는 것이 남아 있습니다 login configuration file. 이에 대한 설명은 Tomcat 문서 " The Realm Component "에서 찾을 수 있습니다.
JAAS - 기술 소개(1부) - 7
즉, 웹 애플리케이션의 리소스에 JAAS Login Config 설정을 배치할 수 있으며 Tomcat Context 덕분에 이를 사용할 수 있습니다. 이 파일은 ClassLoader의 리소스로 사용할 수 있어야 하므로 경로는 다음과 같아야 합니다. \src\main\resources\jaas.config 이 파일의 내용을 설정해 보겠습니다.
JaasLogin {
    jaas.login.JaasLoginModule required debug=true;
};
context.xml여기서도 같은 이름이 사용된다는 점은 주목할 가치가 있습니다 . 이는 보안 영역을 LoginModule에 매핑합니다. 따라서 Tomcat Context는 어떤 클래스가 주체를 나타내는지, 어떤 LoginModule을 사용할지 알려줍니다. 우리가 해야 할 일은 이 LoginModule을 구현하는 것뿐입니다. LoginModule은 아마도 JAAS에서 가장 흥미로운 것 중 하나일 것입니다. 공식 문서는 LoginModule: " JAAS(Java Authentication and Authorization Service): LoginModule 개발자 가이드 "를 개발하는 데 도움이 될 것입니다. 로그인 모듈을 구현해 보겠습니다. 인터페이스를 구현하는 클래스를 만들어 보겠습니다 LoginModule.
public class JaasLoginModule implements LoginModule {
}
먼저 초기화 방법을 설명합니다 LoginModule.
private CallbackHandler handler;
private Subject subject;
@Override
public void initialize(Subject subject, CallbackHandler callbackHandler, <String, ?> sharedState, Map<String, ?> options) {
	handler = callbackHandler;
	this.subject = subject;
}
이 방법을 사용하면 을(를) 저장하고 Subject이를 추가로 인증하고 주체에 대한 정보를 채울 것입니다. 우리는 또한 CallbackHandler우리에게 주어진 미래의 사용을 위해 저축할 것입니다. 도움을 주시면 CallbackHandler조금 후에 인증대상에 대한 다양한 정보를 요청할 수 있습니다. 이에 대한 자세한 내용은 CallbackHandler문서의 해당 섹션인 " JAAS 참조 안내서: CallbackHandler "에서 읽을 수 있습니다. login다음으로 인증을 위한 방법이 실행된다 Subject. 이는 인증의 첫 번째 단계입니다.
@Override
public boolean login() throws LoginException {
	// Добавляем колбэки
	Callback[] callbacks = new Callback[2];
	callbacks[0] = new NameCallback("login");
	callbacks[1] = new PasswordCallback("password", true);
	// При помощи колбэков получаем через CallbackHandler логин и пароль
	try {
		handler.handle(callbacks);
		String name = ((NameCallback) callbacks[0]).getName();
		String password = String.valueOf(((PasswordCallback) callbacks[1]).getPassword());
		// Далее выполняем валидацию.
		// Тут просто для примера проверяем определённые значения
		if (name != null && name.equals("user123") && password != null && password.equals("pass123")) {
			// Сохраняем информацию, которая будет использована в методе commit
			// Не "пачкаем" Subject, т.к. не факт, что commit выполнится
			// Для примера проставим группы вручную, "хардcodeно".
			login = name;
			userGroups = new ArrayList<String>();
			userGroups.add("admin");
			return true;
		} else {
			throw new LoginException("Authentication failed");
		}
	} catch (IOException | UnsupportedCallbackException e) {
		throw new LoginException(e.getMessage());
	}
}
login를 변경하지 않는 것이 중요합니다 Subject. 이러한 변경은 확인 방법에서만 발생해야 합니다 commit. 다음으로, 성공적인 인증을 확인하는 방법을 설명해야 합니다.
@Override
public boolean commit() throws LoginException {
	userPrincipal = new UserPrincipal(login);
	subject.getPrincipals().add(userPrincipal);
	if (userGroups != null && userGroups.size() > 0) {
		for (String groupName : userGroups) {
			rolePrincipal = new RolePrincipal(groupName);
			subject.getPrincipals().add(rolePrincipal);
		}
	}
	return true;
}
메소드 login와 를 분리하는 것이 이상하게 보일 수 있습니다 commit. 그러나 요점은 로그인 모듈을 결합할 수 있다는 것입니다. 성공적인 인증을 위해서는 여러 로그인 모듈이 성공적으로 작동해야 할 수도 있습니다. 필요한 모든 모듈이 작동한 경우에만 변경 사항을 저장하십시오. 이것이 인증의 두 번째 단계입니다. abort및 메소드 로 마무리하겠습니다 logout.
@Override
public boolean abort() throws LoginException {
	return false;
}
@Override
public boolean logout() throws LoginException {
	subject.getPrincipals().remove(userPrincipal);
	subject.getPrincipals().remove(rolePrincipal);
	return true;
}
abort인증의 첫 번째 단계가 실패하면 이 메서드가 호출됩니다. logout시스템이 로그아웃되면 메소드가 호출됩니다. 우리의 것을 구현 Login Module하고 구성한 후에는 이제 특정 것을 사용하고 싶다는 사실을 Security Realm표시해야 합니다 . web.xmlLogin Config
<login-config>
  <auth-method>BASIC</auth-method>
  <realm-name>JaasLogin</realm-name>
</login-config>
보안 영역의 이름을 지정하고 인증 방법 - BASIC을 지정했습니다. 이는 " 13.6 인증 " 섹션의 Servlet API에 설명된 인증 유형 중 하나입니다 . 남은 n
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION