JAX-RS Jersey REST API 安全/身份验证示例

位置:首页>文章>详情   分类: Java教程 > 编程技术   阅读(332)   2023-06-26 07:54:18

在此Jersey rest 安全示例中,我们将学习使用基本身份验证保护Jersey REST API。这将强制每个用户提供用户名/密码以对门户进行身份验证。此外,用户还必须具有一定级别的角色。我从为 RESTEasy API 安全性 创建的其他示例扩展了这个示例,并使用了 ContainerRequestFilter 实现在用户登陆实际 REST API 之前验证用户的访问权限。

1.创建请求鉴权过滤器

我们知道 JAX-RS 2.0 具有用于前后请求处理的过滤器,因此我们将使用 ContainerRequestFilter 接口。在此过滤器中,我们将获取请求尝试访问的方法的详细信息。

我们将找出该方法的所有安全相关配置,并验证此过滤器中的所有内容,例如注释如 @PermitAll@DenyAll@RolesAllowed

根据应用在方法上的注释,我们将决定通过或阻止请求。

package com.cundage.jersey.provider;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;

import javax.annotation.security.DenyAll;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;

import org.glassfish.jersey.internal.util.Base64;

/**
 * This filter verify the access permissions for a user
 * based on username and passowrd provided in request
 * */
@Provider
public class AuthenticationFilter implements javax.ws.rs.container.ContainerRequestFilter
{
	
	@Context
    private ResourceInfo resourceInfo;
	
    private static final String AUTHORIZATION_PROPERTY = "Authorization";
    private static final String AUTHENTICATION_SCHEME = "Basic";
     
    @Override
    public void filter(ContainerRequestContext requestContext)
    {
        Method method = resourceInfo.getResourceMethod();
        //Access allowed for all
        if( ! method.isAnnotationPresent(PermitAll.class))
        {
            //Access denied for all
            if(method.isAnnotationPresent(DenyAll.class))
            {
                requestContext.abortWith(Response.status(Response.Status.FORBIDDEN)
                         .entity("Access blocked for all users !!").build(););
                return;
            }
             
            //Get request headers
            final MultivaluedMap<String, String> headers = requestContext.getHeaders();
             
            //Fetch authorization header
            final List<String> authorization = headers.get(AUTHORIZATION_PROPERTY);
             
            //If no authorization information present; block access
            if(authorization == null || authorization.isEmpty())
            {
                requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED)
                    .entity("You cannot access this resource").build());
                return;
            }
             
            //Get encoded username and password
            final String encodedUserPassword = authorization.get(0).replaceFirst(AUTHENTICATION_SCHEME + " ", "");
             
            //Decode username and password
            String usernameAndPassword = new String(Base64.decode(encodedUserPassword.getBytes()));;
 
            //Split username and password tokens
            final StringTokenizer tokenizer = new StringTokenizer(usernameAndPassword, ":");
            final String username = tokenizer.nextToken();
            final String password = tokenizer.nextToken();
             
            //Verifying Username and password
            System.out.println(username);
            System.out.println(password);
             
            //Verify user access
            if(method.isAnnotationPresent(RolesAllowed.class))
            {
                RolesAllowed rolesAnnotation = method.getAnnotation(RolesAllowed.class);
                Set<String> rolesSet = new HashSet<String>(Arrays.asList(rolesAnnotation.value()));
                 
                //Is user valid?
                if( ! isUserAllowed(username, password, rolesSet))
                {
                    requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED)
                        .entity("You cannot access this resource").build(););
                    return;
                }
            }
        }
    }
    private boolean isUserAllowed(final String username, final String password, final Set<String> rolesSet)
    {
        boolean isAllowed = false;
         
        //Step 1. Fetch password from database and match with password in argument
        //If both match then get the defined role for user from database and continue; else return isAllowed [false]
        //Access the database and do this part yourself
        //String userRole = userMgr.getUserRole(username);
        
        if(username.equals("cundage") && password.equals("password"))
        {
        	String userRole = "ADMIN";
            
            //Step 2. Verify user role
            if(rolesSet.contains(userRole))
            {
                isAllowed = true;
            }
        }
        return isAllowed;
    }
}

2.向ResourceConfig注册AuthenticationFilter

现在您需要使用 ResourceConfig 实例注册上述过滤器。所以创建一个如下所示的实例:

package com.cundage.jersey;

import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.server.ResourceConfig;
import com.cundage.jersey.provider.AuthenticationFilter;
import com.cundage.jersey.provider.GsonMessageBodyHandler;

public class CustomApplication extends ResourceConfig 
{
	public CustomApplication() 
	{
		packages("com.cundage.jersey");
		register(LoggingFilter.class);
		register(GsonMessageBodyHandler.class);

		//Register Auth Filter here
		register(AuthenticationFilter.class);
	}
}

并在 web.xml 文件中添加此资源配置。

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>

	<display-name>Archetype Created Web Application</display-name>

	<servlet>
		<servlet-name>jersey-serlvet</servlet-name>
		<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
		<init-param>
			<param-name>javax.ws.rs.Application</param-name>
			<param-value>com.cundage.jersey.CustomApplication</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>jersey-serlvet</servlet-name>
		<url-pattern>/rest/*</url-pattern>
	</servlet-mapping>

</web-app>

3. 安全的 REST API

现在是保护 REST API 的时候了。像下面这样使用标准的 JAX-RS 注释。

@Path("/employees")
public class JerseyService 
{
	@RolesAllowed("ADMIN")
	@GET
	@Produces(MediaType.APPLICATION_JSON)
	@Consumes(MediaType.APPLICATION_JSON)
	public Employees getAllEmployees() 
	{
		Employees list = new Employees();
		list.setEmployeeList(new ArrayList<Employee>());
		
		list.getEmployeeList().add(new Employee(1, "Lokesh Gupta"));
		list.getEmployeeList().add(new Employee(2, "Alex Kolenchiskey"));
		list.getEmployeeList().add(new Employee(3, "David Kameron"));
		
		return list;
	}
}

4. 测试 Jersey AuthenticationFilter

让我们测试身份验证设置是否有效。

命中网址:http://localhost:8080/JerseyDemos/rest/employees

Jersey authentication failure request

在基本身份验证参数中传递用户名和密码:howtodoinjava/password

Jersey authenticated success request

单击下面的链接下载jersey rest api 身份验证示例 应用程序的源代码。

泽西演示

快乐学习!!

标签2: Jersey JAX-RS
地址:https://www.cundage.com/article/jersey-rest-security.html

相关阅读

Jersey 是 JAX-RS 2.1 的参考实现。为了在企业容器之外运行具有 JSON-P 和 JSON-B 映射的 JAX-RS 2.1 客户端,需要以下 Jersey 依赖项。 Jerse...
Jersey 是 JAX-RS 2.1 的参考实现。为了在企业容器之外运行具有 JSON-P 和 JSON-B 映射的 JAX-RS 2.1 客户端,需要以下 Jersey 依赖项。 Jerse...
在此Jersey rest 安全示例中,我们将学习使用基本身份验证保护Jersey REST API。这将强制每个用户提供用户名/密码以对门户进行身份验证。此外,用户还必须具有一定级别的角色。我...
默认情况下,在 JAX-RS 中,@Path 注释中指定的所有 URL 都是CASE-SENSITIVE。在本教程中,我给出了一个简单的 CASE-INSENSITIVE URL 示例,可以在任...
当对 REST 服务的请求到来时,JAX-RS 运行时如何启动它?它是否只保留 JAX-RS 资源的一个对象并为每个请求生成一个新线程?或者它是否为每个请求启动该 JAX-RS 资源类的新对象?...
学习使用 Spring Boot 和 Jersey 框架配置和创建 JAX-RS 2.0 REST API。此示例应用程序使用 Jersey 的 ServletContainer 来部署 RES...
在 Jersey ExceptionMapper 示例中,我们将学习使用 ExceptionMapper 接口,同时开发 Jersey RESTful Web 服务。出于演示目的,我正在修改为球...
在 Restlet 之后,Jersey 是另一个流行的开源框架,用于在 Java 中创建 RESTful web 服务。 Jersey 符合 JAX-RS 规范,实际上它是 JAX-RS (JS...
学习使用 Spring Boot 和 Jersey 框架创建 JAX-RS 2.0 REST API,并添加 &lt; strong&gtl;基于角色的安全性 使用 JAX-RS 注释,例如@P...
学习使用它的 javax.ws.rs.core.链接, javax.ws.rs.core.UriBuilder 和 javax.ws.rs.core.UriInfo 类。 RESTEasy 3....