Java JAX-RS安全性-主体未持久化

Java JAX-RS安全性-主体未持久化,java,jakarta-ee,jax-rs,wildfly,resteasy,Java,Jakarta Ee,Jax Rs,Wildfly,Resteasy,首先是守则: 应用程序设置类: @ApplicationPath("/rest") public class ApplicationConfig extends Application { } JAX-RS资源类: @Path("/test") @RequestScoped public class TestWS { @POST @Path("/login") @Produces(MediaTyp

首先是守则:

应用程序设置类:

    @ApplicationPath("/rest")
    public class ApplicationConfig extends Application {

    }
JAX-RS资源类:

    @Path("/test")
    @RequestScoped
    public class TestWS {
        @POST
        @Path("/login")
        @Produces(MediaType.TEXT_PLAIN)
        public Response login(@Context HttpServletRequest req){
            req.getSession().setAttribute("test","test");
            System.out.println(req.getSession().getId());
            if(req.getUserPrincipal() == null){
                String authHeader = req.getHeader(HttpHeaders.AUTHORIZATION);
                if(authHeader != null && !authHeader.isEmpty()){
                    String base64Credentials = authHeader.substring("Basic".length()).trim();
                    String credentials = new String(Base64.getDecoder().decode(base64Credentials),
                            Charset.forName("UTF-8"));
                    final String[] values = credentials.split(":",2);
                    try {
                        req.login(values[0], values[1]);
                        System.out.println(req.getUserPrincipal().toString());
                    }
                    catch(ServletException e){
                        e.printStackTrace();
                        return Response.status(Response.Status.UNAUTHORIZED).build();
                    }
                }
            }else{
                System.out.println(req.getUserPrincipal());
                System.out.println(req.isUserInRole("User"));
                req.getServletContext().log("Skipped logged because already logged in!");
            }

            req.getServletContext().log("Authentication Demo: successfully retrieved User Profile!");
            return Response.ok().build();
        }

        @Path("/ping")
        @Produces(MediaType.APPLICATION_JSON)
        @GET
        public String ping(@Context HttpServletRequest req){
            Object test = req.getSession().getAttribute("test");
            System.out.println(req.getSession().getId());
            System.out.println(test);
            System.out.println(req.getUserPrincipal());
            System.out.println(req.isUserInRole("User"));
            return "{\"status\":\"ok\"}";
        }
    }
web.xml:

    <?xml version="1.0" encoding="UTF-8" ?>
    <web-app>
        <context-param>
            <param-name>resteasy.role.based.security</param-name>
            <param-value>true</param-value>
        </context-param>

        <security-constraint>
            <web-resource-collection>
                <web-resource-name>rest</web-resource-name>
                <url-pattern>/rest/*</url-pattern>
                <http-method>GET</http-method>
                <http-method>POST</http-method>
                <http-method>PUT</http-method>
                <http-method>DELETE</http-method>
            </web-resource-collection>
            <user-data-constraint>
                <transport-guarantee>NONE</transport-guarantee>
            </user-data-constraint>
        </security-constraint>

        <welcome-file-list>
            <welcome-file>index.html</welcome-file>
        </welcome-file-list>

        <session-config>
            <session-timeout>30</session-timeout>
        </session-config>

        <login-config>
            <auth-method>BASIC</auth-method>
            <realm-name>PBKDF2DatabaseDomain</realm-name>
        </login-config>
    </web-app>

resteasy.role.based.security
真的
休息
/休息/*
得到
邮递
放
删除
没有一个
index.html
30


但是登录方法中的修复设置会话属性对我不起作用。

一些提示和备注:

  • 由于REST是无状态的,我将在客户端管理会话,而不是在服务器端持久化客户端状态
  • 无状态身份验证可以通过返回每个请求/服务的基本身份验证头来实现,这些请求/服务只限于经过身份验证的用户,例如/login和/ping
  • /当用户未得到很好的身份验证和识别时,登录服务可能会抛出WebApplicationException,以便您的客户端应用程序管理它并向最终用户显示身份验证错误消息。 然后,您可以使用@RolesAllowed('something')注释和/ping方法上方的JAAS来限制具有“something”角色的经过身份验证的用户的访问。因此,您将不再需要编写身份验证或授权代码,并从应用程序中的授权层中获益

所有这些都可以通过JavaEE7在Wildfly上实现,无需额外的库。

Basic auth。是无状态的
。如果显式地将其配置为persist/cache,则会保存它。尝试将表单auth分开。和基本身份验证。如果它在同一个资源(test/login)上持续存在,它怎么会是无状态的呢?第二次调用test/login没有auth头…而且我似乎找不到任何关于如何将基本身份验证配置为非stateles的文档-持续存在/缓存…我没有用JBOSS尝试过,但用tomcat,我在这个例子中使用了like是的,但这是使用spring安全依赖库,我不想使用它=)是的,现在我使用手动登录和HttpServletRequest##登录和注销。不过,我将把它包装成一个完全无状态的用户会话跟踪。非常感谢。
    <?xml version="1.0" encoding="UTF-8"?>
    <jboss-web>
        <context-root>/</context-root>
        <security-domain>PBKDF2DatabaseDomain</security-domain>
    </jboss-web>
    <subsystem xmlns="urn:jboss:domain:security:1.2">
        <security-domains>
            <security-domain name="PBKDF2DatabaseDomain" cache-type="default">
                <authentication>
                    <login-module code="de.rtner.security.auth.spi.SaltedDatabaseServerLoginModule" flag="required" module="de.rtner.PBKDF2">
                        <module-option name="dsJndiName" value="java:jboss/datasources/developmentDS"/>
                        <module-option name="principalsQuery" value="SELECT password FROM ur.user WHERE username=?"/>
                        <module-option name="rolesQuery" value="select distinct r.NAME, 'Roles' from ur.user_roles ur left join ur.ct_role r on ur.ROLE_ID = r.ID left join ur.user u on ur.USER_ID = u.ID where u.username =?"/>
                    </login-module>
                </authentication>
            </security-domain>
...