programing

JAX-RS 및 Jersey를 사용한 REST 토큰 기반 인증 구현 방법

copyandpastes 2022. 7. 13. 21:37
반응형

JAX-RS 및 Jersey를 사용한 REST 토큰 기반 인증 구현 방법

Jersey에서 토큰 기반 인증을 활성화하는 방법을 찾고 있습니다.나는 어떤 특정한 틀도 사용하지 않으려고 노력하고 있다.가능할까요?

내 계획은 사용자가 내 웹 서비스에 등록하고 내 웹 서비스가 토큰을 생성하여 클라이언트에 보내면 클라이언트는 이를 보유한다는 것입니다.그러면 클라이언트는 각 요구에 대해 사용자 이름과 비밀번호 대신 토큰을 전송합니다.

@PreAuthorize("hasRole('ROLE')")토큰이 유효한지 여부를 확인하기 위해 데이터베이스에 대한 요구가 많다고 생각했을 뿐입니다.

아니면 필터를 작성하지 않고 각 요청에 파라미터 토큰을 넣습니까?따라서 각 API는 처음에 토큰을 확인하고 그 후에 리소스를 취득하기 위해 무언가를 실행합니다.

토큰 기반 인증 구조

토큰 기반 인증에서는 클라이언트는 토큰이라는 데이터 조각과 하드 자격 정보(사용자 이름 및 암호 등)를 교환합니다.각 요구에 대해서, 클라이언트는 하드 credential을 송신하는 대신에, 서버에 토큰을 송신하고, 인증과 인가를 실시합니다.

한마디로 토큰에 기초한 인증방식은 다음 절차를 따릅니다.

  1. 클라이언트는, 자격 정보(사용자명과 패스워드)를 서버에 송신합니다.
  2. 서버는 credential을 인증하고 유효한 경우 사용자용 토큰을 생성합니다.
  3. 서버는 이전에 생성된 토큰을 사용자 ID 및 만료 날짜와 함께 일부 저장소에 저장합니다.
  4. 서버는 생성된 토큰을 클라이언트에 전송합니다.
  5. 클라이언트는 각 요청에서 토큰을 서버로 전송합니다.
  6. 서버는, 각 요구로 착신 요구로부터 토큰을 추출합니다.토큰을 사용하면 서버는 인증을 수행하기 위해 사용자 세부사항을 검색합니다.
    • 토큰이 유효한 경우 서버는 요청을 수락합니다.
    • 토큰이 유효하지 않은 경우 서버는 요청을 거부합니다.
  7. 인증이 실행되면 서버는 인가를 수행합니다.
  8. 서버는 토큰을 새로 고치는 엔드포인트를 제공할 수 있습니다.

JAX-RS 2.0(Jersey, RESTEasy 및 Apache CXF)으로 수행할 수 있는 작업

이 솔루션에서는 JAX-RS 2.0 API만을 사용하여 벤더 고유의 솔루션을 사용하지 않습니다.따라서 JAX-RS 2.0 구현(Jersey, RESTEASY, Apache CXF )과 연동해야 합니다.

기반을 사용하는 웹 하지 않고 어플리케이션의 EE를 할 수 .web.xml커스텀 인증입니다.

사용자 이름과 비밀번호로 사용자 인증 및 토큰 발행

자격 증명(사용자 이름 및 암호)을 수신하고 검증하는 JAX-RS 리소스 메서드를 만들고 사용자에게 토큰을 발급합니다.

@Path("/authentication")
public class AuthenticationEndpoint {

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public Response authenticateUser(@FormParam("username") String username, 
                                     @FormParam("password") String password) {

        try {

            // Authenticate the user using the credentials provided
            authenticate(username, password);

            // Issue a token for the user
            String token = issueToken(username);

            // Return the token on the response
            return Response.ok(token).build();

        } catch (Exception e) {
            return Response.status(Response.Status.FORBIDDEN).build();
        }      
    }

    private void authenticate(String username, String password) throws Exception {
        // Authenticate against a database, LDAP, file or whatever
        // Throw an Exception if the credentials are invalid
    }

    private String issueToken(String username) {
        // Issue a token (can be a random String persisted to a database or a JWT token)
        // The issued token must be associated to a user
        // Return the issued token
    }
}

시 가 " " " " "인 입니다.403(서양속담, 친구속담)

검증되면 credential을 가진 .200(OK)가 반환되고 발행된 토큰이 응답 페이로드로 클라이언트에 전송됩니다.클라이언트는 모든 요청에서 토큰을 서버로 전송해야 합니다.

비시를 할 때application/x-www-form-urlencodedpayload의 predential.

username=admin&password=123456

폼 파라미터 대신 사용자 이름과 비밀번호를 클래스로 랩할 수 있습니다.

public class Credentials implements Serializable {

    private String username;
    private String password;
    
    // Getters and setters omitted
}

다음으로 JSON으로 소비합니다.

@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response authenticateUser(Credentials credentials) {

    String username = credentials.getUsername();
    String password = credentials.getPassword();
    
    // Authenticate the user, issue a token and return a response
}

이 방법을 사용하면 클라이언트는 요구의 페이로드에 다음 형식으로 credential을 전송해야 합니다.

{
  "username": "admin",
  "password": "123456"
}

요청에서 토큰 추출 및 검증

.Authorization를 들어 과 같습니다예를 들어 다음과 같습니다.

Authorization: Bearer <token-goes-here>

표준 HTTP 헤더의 이름은 허가가 아닌 인증 정보를 전송하기 때문에 유감입니다.단, 서버에 자격 증명을 보내기 위한 표준 HTTP 헤더입니다.

JAX-RS는 필터 및 인터셉터를 리소스 클래스 및 메서드에 바인딩하기 위해 다른 주석을 작성하기 위해 사용되는 메타 주석을 제공합니다.의 정의@Secured★★★★

@NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Secured { }

위에서 정의한 이름 바인딩 주석은 필터 클래스를 꾸미기 위해 사용됩니다. 필터 클래스는 리소스 메서드에 의해 처리되기 전에 요청을 대행 수신할 수 있습니다.를 사용하여 HTTP 요청 헤더에 액세스하여 토큰을 추출할 수 있습니다.

@Secured
@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {

    private static final String REALM = "example";
    private static final String AUTHENTICATION_SCHEME = "Bearer";

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {

        // Get the Authorization header from the request
        String authorizationHeader =
                requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);

        // Validate the Authorization header
        if (!isTokenBasedAuthentication(authorizationHeader)) {
            abortWithUnauthorized(requestContext);
            return;
        }

        // Extract the token from the Authorization header
        String token = authorizationHeader
                            .substring(AUTHENTICATION_SCHEME.length()).trim();

        try {

            // Validate the token
            validateToken(token);

        } catch (Exception e) {
            abortWithUnauthorized(requestContext);
        }
    }

    private boolean isTokenBasedAuthentication(String authorizationHeader) {

        // Check if the Authorization header is valid
        // It must not be null and must be prefixed with "Bearer" plus a whitespace
        // The authentication scheme comparison must be case-insensitive
        return authorizationHeader != null && authorizationHeader.toLowerCase()
                    .startsWith(AUTHENTICATION_SCHEME.toLowerCase() + " ");
    }

    private void abortWithUnauthorized(ContainerRequestContext requestContext) {

        // Abort the filter chain with a 401 status code response
        // The WWW-Authenticate header is sent along with the response
        requestContext.abortWith(
                Response.status(Response.Status.UNAUTHORIZED)
                        .header(HttpHeaders.WWW_AUTHENTICATE, 
                                AUTHENTICATION_SCHEME + " realm=\"" + REALM + "\"")
                        .build());
    }

    private void validateToken(String token) throws Exception {
        // Check if the token was issued by the server and if it's not expired
        // Throw an Exception if the token is invalid
    }
}

가 "" " " " " 의 입니다.401(무허가)가 반환됩니다.그렇지 않으면 요청은 리소스 메서드로 진행됩니다.

REST 엔드포인트 보호

클래스에 , 「」로 .@Secured주석 작성.주석이 달린 메서드 및/또는 클래스에 대해 필터가 실행됩니다.즉, 요청이 유효한 토큰을 사용하여 수행된 경우에만 이러한 엔드포인트에 도달합니다.

인증이 필요 없는 메서드 또는 클래스가 있는 경우 주석을 달지 마십시오.

@Path("/example")
public class ExampleResource {

    @GET
    @Path("{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response myUnsecuredMethod(@PathParam("id") Long id) {
        // This method is not annotated with @Secured
        // The authentication filter won't be executed before invoking this method
        ...
    }

    @DELETE
    @Secured
    @Path("{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response mySecuredMethod(@PathParam("id") Long id) {
        // This method is annotated with @Secured
        // The authentication filter will be executed before invoking this method
        // The HTTP request must be performed with a valid token
        ...
    }
}

위의 예에서 필터는 다음 명령어에 대해서만 실행됩니다.mySecuredMethod(Long) 방법에는@Secured.

현재 사용자 식별

REST API를 다시 요청하고 있는 사용자를 알아야 합니다.이를 달성하기 위해 다음과 같은 방법을 사용할 수 있습니다.

현재 요청의 보안 컨텍스트 재정의

메서드 내에서 현재 요청에 대해 새 인스턴스를 설정할 수 있습니다.다음으로 를 덮어쓰고 인스턴스를 반환합니다.

final SecurityContext currentSecurityContext = requestContext.getSecurityContext();
requestContext.setSecurityContext(new SecurityContext() {

        @Override
        public Principal getUserPrincipal() {
            return () -> username;
        }

    @Override
    public boolean isUserInRole(String role) {
        return true;
    }

    @Override
    public boolean isSecure() {
        return currentSecurityContext.isSecure();
    }

    @Override
    public String getAuthenticationScheme() {
        return AUTHENTICATION_SCHEME;
    }
});

토큰을 사용하여 사용자 ID(사용자 이름)를 검색합니다.이 ID는 의 이름이 됩니다.

임의의 JAX-RS 자원 클래스에 를 삽입합니다.

@Context
SecurityContext securityContext;

JAX-RS 리소스 방식에서도 동일한 작업을 수행할 수 있습니다.

@GET
@Secured
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response myMethod(@PathParam("id") Long id, 
                         @Context SecurityContext securityContext) {
    ...
}

그리고 다음 정보를 얻습니다.

Principal principal = securityContext.getUserPrincipal();
String username = principal.getName();

CDI(Context and Dependency Injection) 사용

어떤 이유로 덮어쓰지 않을 경우 이벤트나 제작자 등의 유용한 기능을 제공하는 CDI(Context and Dependency Injection)를 사용할 수 있습니다.

CDI 한정자를 만듭니다.

@Qualifier
@Retention(RUNTIME)
@Target({ METHOD, FIELD, PARAMETER })
public @interface AuthenticatedUser { }

고객님의 고객명AuthenticationFilter위에서 작성한 주석 삽입@AuthenticatedUser:

@Inject
@AuthenticatedUser
Event<String> userAuthenticatedEvent;

인증이 성공하면 사용자 이름을 파라미터로 전달하는 이벤트를 실행합니다(이 토큰은 사용자에 대해 발행되며 토큰은 사용자 ID 검색에 사용됩니다).

userAuthenticatedEvent.fire(username);

응용 프로그램에 사용자를 나타내는 클래스가 있을 수 있습니다.이 반을 을을부라고 .User.

이벤트를 CDI bean을 .User하는 사용자 을 할당하고, 을 「」에 합니다.authenticatedUser다음 중 하나:

@RequestScoped
public class AuthenticatedUserProducer {

    @Produces
    @RequestScoped
    @AuthenticatedUser
    private User authenticatedUser;
    
    public void handleAuthenticationEvent(@Observes @AuthenticatedUser String username) {
        this.authenticatedUser = findUser(username);
    }

    private User findUser(String username) {
        // Hit the the database or a service to find a user by its username and return it
        // Return the User instance
    }
}

authenticatedUser[ ]에 의해, 「 」가 됩니다.User컨테이너 관리 콩(JAX-RS 서비스, CDI 콩, 서블릿 및 EJB 등)에 주입할 수 있는 인스턴스입니다.하여 '먹다'를 합니다.UserCDI:

@Inject
@AuthenticatedUser
User authenticatedUser;

CDI 주석은 JAX-RS 주석과 다릅니다.

CDI 주석을 사용하는 것을 확인합니다.AuthenticatedUserProducerbean.bean.contract.

여기서 중요한 것은 필터와 콩 사이에서 데이터를 공유할 수 있도록 주석이 달린 콩입니다.이벤트를 사용하지 않으려면 필터를 수정하여 인증된 사용자를 요청 범위 빈에 저장한 후 JAX-RS 리소스 클래스에서 읽을 수 있습니다.

를 덮어쓰는 어프로치와 달리 CDI 어프로치를 사용하면 JAX-RS 자원 및 공급자 이외의 콩에서 인증된 사용자를 취득할 수 있습니다.

역할 기반 인증 지원

역할 기반 인증을 지원하는 방법에 대한 자세한 내용은 다른 답변을 참조하십시오.

토큰 발행

토큰은 다음과 같습니다.

  • 불투명: 값 자체(임의 문자열 등) 이외의 세부 정보를 표시하지 않습니다.
  • 내장형:토큰 자체에 대한 상세 정보가 포함되어 있습니다(JWT 등).

자세한 내용은 아래를 참조하십시오.

토큰으로서의 랜덤 문자열

토큰은 랜덤 문자열을 생성하여 사용자 식별자 및 유효기간과 함께 데이터베이스에 유지함으로써 발행할 수 있습니다.Java에서 랜덤 문자열을 생성하는 방법의 좋은 예를 여기에서 볼 수 있습니다.다음 항목도 사용할 수 있습니다.

Random random = new SecureRandom();
String token = new BigInteger(130, random).toString(32);

JWT(JSON Web 토큰)

JWT(JSON Web Token)는 두 당사자 간의 클레임을 안전하게 표현하기 위한 표준 방법으로 RFC 7519에 정의되어 있습니다.

이 토큰은 독립형 토큰으로 클레임에 세부 정보를 저장할 수 있습니다.이러한 클레임은 Base64로 부호화된 JSON인 토큰 페이로드에 저장됩니다.다음으로 RFC 7519에 등록된 클레임과 그 의미를 나타냅니다(자세한 내용은 RFC 전문을 참조하십시오).

  • iss: 토큰을 발행한 주체.
  • sub: JWT의 대상이 되는 주체.
  • exp: 토큰의 유효기간.
  • : 토큰이 처리를 위해 받아들여지기 시작하는 시간nbf.
  • : 토큰이 발행된 시각iat.
  • : 토큰의 고유 식별자jti.

암호와 같은 중요한 데이터를 토큰에 저장해서는 안 됩니다.

payload는 클라이언트에서 읽을 수 있으며 토큰의 무결성은 서버에서 서명을 확인함으로써 쉽게 확인할 수 있습니다.시그니처는 토큰의 조작을 방지하는 것입니다.

추적할 필요가 없는 경우에는 JWT 토큰을 유지할 필요가 없습니다.토큰을 유지함으로써 토큰의 액세스를 무효화하고 취소할 수 있습니다.JWT 토큰을 추적하려면 토큰 전체를 서버에 유지하는 대신 토큰을 발행한 사용자, 유효기간 등 기타 세부 정보와 함께 토큰 식별자(jti 클레임)를 유지할 수 있습니다.

토큰을 유지할 때는 데이터베이스가 무한히 커지는 것을 방지하기 위해 오래된 토큰을 삭제하는 것을 항상 고려해 주십시오.

JWT 사용

JWT 토큰을 발행하고 검증하는 Java 라이브러리는 다음과 같습니다.

JWT와 연계할 수 있는 기타 유용한 리소스를 찾으려면 http://jwt.io을 참조하십시오.

JWT를 사용한 토큰 취소 처리

토큰을 해지하려면 토큰을 추적해야 합니다.서버 측에 전체 토큰을 저장할 필요가 없으며 토큰 식별자(일치해야 함) 및 필요한 경우 일부 메타데이터만 저장할 필요가 있습니다.토큰 ID에는 UUID를 사용할 수 있습니다.

클레임을 사용하여 토큰 식별자를 토큰에 저장해야 합니다.토큰을 검증할 때 서버 측에 있는 토큰 식별자에 대해 클레임 값을 확인하여 토큰이 취소되지 않았는지 확인하십시오.

보안을 위해 사용자가 암호를 변경할 때 사용자의 모든 토큰을 해지하십시오.

추가 정보

  • 어떤 종류의 인증을 사용할지는 중요하지 않습니다.man-in-the-middle 공격을 방지하기 위해 항상 HTTPS 접속 상단에서 실행합니다.
  • 토큰에 대한 자세한 내용은 Information Security에서 제공하는 이 질문을 참조하십시오.
  • 이 문서에서는 토큰 기반 인증에 대한 유용한 정보를 제공합니다.

이 답변은 인증에 관한 답변으로, 인증에 관한 이전 답변의 보완입니다.

또 다른 대답을 하죠?JSR-250 주석을 지원하는 방법에 대한 자세한 내용을 추가하여 이전 답변을 확장하려고 했습니다.그러나 원래의 답은 너무 길어졌고 최대 길이인 30,000자를 초과했다.그래서 인증 세부사항을 모두 이 답변으로 옮겼습니다.다른 답변은 인증과 토큰 발행에 중점을 두고 있습니다.


@Secured

다른 응답에 나타난 인증 흐름 외에 REST 엔드 포인트에서는 롤 기반 인가를 지원할 수 있습니다.

열거를 작성하고 필요에 따라 역할을 정의합니다.

public enum Role {
    ROLE_1,
    ROLE_2,
    ROLE_3
}

변경합니다.@Secured역할을 지원하기 위해 이전에 만든 이름 바인딩 주석:

@NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Secured {
    Role[] value() default {};
}

다음 자원 을 달아주세요.@Secured인가를 실행합니다.메서드 주석이 클래스 주석을 재정의합니다.

@Path("/example")
@Secured({Role.ROLE_1})
public class ExampleResource {

    @GET
    @Path("{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response myMethod(@PathParam("id") Long id) {
        // This method is not annotated with @Secured
        // But it's declared within a class annotated with @Secured({Role.ROLE_1})
        // So it only can be executed by the users who have the ROLE_1 role
        ...
    }

    @DELETE
    @Path("{id}")    
    @Produces(MediaType.APPLICATION_JSON)
    @Secured({Role.ROLE_1, Role.ROLE_2})
    public Response myOtherMethod(@PathParam("id") Long id) {
        // This method is annotated with @Secured({Role.ROLE_1, Role.ROLE_2})
        // The method annotation overrides the class annotation
        // So it only can be executed by the users who have the ROLE_1 or ROLE_2 roles
        ...
    }
}

priority를 가진 필터를 만듭니다.이 필터는 이전에 정의된 priority 필터 후에 실행됩니다.

를 사용하여 요구를 처리할 리소스와 리소스를 취득한 후@Secured★★★★

@Secured
@Provider
@Priority(Priorities.AUTHORIZATION)
public class AuthorizationFilter implements ContainerRequestFilter {

    @Context
    private ResourceInfo resourceInfo;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {

        // Get the resource class which matches with the requested URL
        // Extract the roles declared by it
        Class<?> resourceClass = resourceInfo.getResourceClass();
        List<Role> classRoles = extractRoles(resourceClass);

        // Get the resource method which matches with the requested URL
        // Extract the roles declared by it
        Method resourceMethod = resourceInfo.getResourceMethod();
        List<Role> methodRoles = extractRoles(resourceMethod);

        try {

            // Check if the user is allowed to execute the method
            // The method annotations override the class annotations
            if (methodRoles.isEmpty()) {
                checkPermissions(classRoles);
            } else {
                checkPermissions(methodRoles);
            }

        } catch (Exception e) {
            requestContext.abortWith(
                Response.status(Response.Status.FORBIDDEN).build());
        }
    }

    // Extract the roles from the annotated element
    private List<Role> extractRoles(AnnotatedElement annotatedElement) {
        if (annotatedElement == null) {
            return new ArrayList<Role>();
        } else {
            Secured secured = annotatedElement.getAnnotation(Secured.class);
            if (secured == null) {
                return new ArrayList<Role>();
            } else {
                Role[] allowedRoles = secured.value();
                return Arrays.asList(allowedRoles);
            }
        }
    }

    private void checkPermissions(List<Role> allowedRoles) throws Exception {
        // Check if the user contains one of the allowed roles
        // Throw an Exception if the user has not permission to execute the method
    }
}

은 """로 됩니다"""는 ""로 됩니다.403(신호)

요청을 수행하는 사용자를 확인하려면 이전 답변을 참조하십시오.사용하는 어프로치에 따라서, 에서 취득할 수도, CDI 를 사용해 주입할 수도 있습니다.

「」의 '@Secured이치노 인증된 모든 사용자가 해당 엔드포인트에 액세스할 수 있으며 사용자의 역할은 무시한다고 가정할 수 있습니다.

JSR-250 어노테이션에 의한 롤 베이스

의 롤을 도 있습니다.@Secured상기와 같이 주석, 및 등의 JSR-250 주석을 고려할 수 있습니다.

JAX-RS는 이러한 주석을 즉시 사용할 수 없지만 필터를 통해 이를 달성할 수 있습니다.이 모든 것을 서포트하는 경우는, 다음의 점에 주의해 주세요.

  • @DenyAll 메서드에서는 클래스보다 우선됩니다.
  • @RolesAllowed method가 클래스보다 우선합니다.
  • @PermitAll method가 클래스보다 우선합니다.
  • @DenyAll 수업에 연결할 수 없습니다.
  • @RolesAllowed 클래스보다 우선합니다.

따라서 JSR-250 주석을 체크하는 인가 필터는 다음과 같습니다.

@Provider
@Priority(Priorities.AUTHORIZATION)
public class AuthorizationFilter implements ContainerRequestFilter {

    @Context
    private ResourceInfo resourceInfo;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {

        Method method = resourceInfo.getResourceMethod();

        // @DenyAll on the method takes precedence over @RolesAllowed and @PermitAll
        if (method.isAnnotationPresent(DenyAll.class)) {
            refuseRequest();
        }

        // @RolesAllowed on the method takes precedence over @PermitAll
        RolesAllowed rolesAllowed = method.getAnnotation(RolesAllowed.class);
        if (rolesAllowed != null) {
            performAuthorization(rolesAllowed.value(), requestContext);
            return;
        }

        // @PermitAll on the method takes precedence over @RolesAllowed on the class
        if (method.isAnnotationPresent(PermitAll.class)) {
            // Do nothing
            return;
        }

        // @DenyAll can't be attached to classes

        // @RolesAllowed on the class takes precedence over @PermitAll on the class
        rolesAllowed = 
            resourceInfo.getResourceClass().getAnnotation(RolesAllowed.class);
        if (rolesAllowed != null) {
            performAuthorization(rolesAllowed.value(), requestContext);
        }

        // @PermitAll on the class
        if (resourceInfo.getResourceClass().isAnnotationPresent(PermitAll.class)) {
            // Do nothing
            return;
        }

        // Authentication is required for non-annotated methods
        if (!isAuthenticated(requestContext)) {
            refuseRequest();
        }
    }

    /**
     * Perform authorization based on roles.
     *
     * @param rolesAllowed
     * @param requestContext
     */
    private void performAuthorization(String[] rolesAllowed, 
                                      ContainerRequestContext requestContext) {

        if (rolesAllowed.length > 0 && !isAuthenticated(requestContext)) {
            refuseRequest();
        }

        for (final String role : rolesAllowed) {
            if (requestContext.getSecurityContext().isUserInRole(role)) {
                return;
            }
        }

        refuseRequest();
    }

    /**
     * Check if the user is authenticated.
     *
     * @param requestContext
     * @return
     */
    private boolean isAuthenticated(final ContainerRequestContext requestContext) {
        // Return true if the user is authenticated or false otherwise
        // An implementation could be like:
        // return requestContext.getSecurityContext().getUserPrincipal() != null;
    }

    /**
     * Refuse the request.
     */
    private void refuseRequest() {
        throw new AccessDeniedException(
            "You don't have permissions to perform this action.");
    }
}

주의: 상기 실장은 Jersey에 근거하고 있습니다.Jersey를 사용하는 경우 필터를 직접 작성할 필요가 없습니다.기존의 실장만 사용하면 됩니다.

언급URL : https://stackoverflow.com/questions/26777083/how-to-implement-rest-token-based-authentication-with-jax-rs-and-jersey

반응형