Java >> Java tutorial >  >> Java

Få logget ind brugeroplysninger i Jakarta EE – den enkleste måde

Sikkerheden før Java EE 8 / Jakarta EE 8 plejede at være en smule kompliceret og forvirrende. Hver specifikation gav sin egen måde at hente oplysninger om den loggede bruger på. Situationen blev markant forbedret med introduktionen af ​​Security API, der giver en samlet måde at gøre det på – blot injicer SecurityContext CDI-bønnen.

Der er stadig en lille hake - dette virker kun i servlet-sammenhæng og EJB-sammenhæng. Eller med andre ord, når du behandler en HTTP-anmodning eller inde i enhver type EJB. Det gode er, at dette dækker de fleste tilfælde, hvor du nogensinde får brug for at hente brugeroplysninger. I de andre sjældne tilfælde skal du bruge en af ​​de API'er, som jeg også beskriver i dette indlæg.

Enslet adgang til brugeroplysninger ved hjælp af Security API

Med Security API er det ret nemt at hente oplysninger om den aktuelle bruger:

  • Injicer SecurityContext
  • Hent navnet på brugeren
    • Kald metoden getCallerPrincipal()
    • Hvis resultatet er null , ingen bruger er logget ind
    • Ellers skal du kalde metoden getName() for at få navnet på den loggede bruger
  • Bekræft, at en bruger har en specifik rolle (tilladelse)
    • Kald metoden isCallerInRole(roleName)

Komplet eksempel på en servlet, der udskriver brugerens navn, og om brugeren er i rollen "admin":

@WebServlet(urlPatterns = "/servlet")
public class UserInfoServlet extends HttpServlet {

    @Inject
    SecurityContext userContext;
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // retrieve the principal and later check whether it's null or not
        Principal callerPrincipal = userContext.getCallerPrincipal();

        resp.getOutputStream().println(String.format(
                "<html><body>"
                + "<p>User: %s</p>"
                + "<p>Is admin: %s</p>"
              + "</body></html>", 

        // print user's name only if the user is logger in and principal is not null
                callerPrincipal != null ? callerPrincipal.getName() : "not logged in",
        // true if user has admin role
                userContext.isCallerInRole("admin")));
    }
    
}

Alternative måder at få adgang til brugeroplysninger på

I tilfælde af at du ikke kan bruge Security API, kan du stadig bruge en af ​​de andre API'er, der giver lignende adgang til brugeroplysninger. En masse andre specifikations-API'er giver lignende metoder til at hente navnet på den loggede bruger og til at kontrollere, om brugeren er i en bestemt rolle. Nedenfor er en oversigt over alle mulige måder:

Specifikation API Metoder til at ringe Sådan henter du brugerkonteksten
Servlet Brugernavn: HttpServletRequest.getUserPrincipal ()

Returnerer null hvis du ikke er logget ind.

I rolle: HttpServletRequest.isUserInRole ()
@Inject
HttpServletRequest request;


HttpServletRequest videregives også til servlets metoder
EJB Brugernavn: EJBContext.getCallerPrincipal()

Hvis du ikke er logget ind, returneres en Principal med getName() == "ANONYMOUS" i stedet for null

I rolle:
EJBContext.isCallerInRole()
EJBContext eller enhver af dens undergrænseflader kan injiceres i en EJB eller hentes via JNDI:

@Resource
EJBContext ejbContext;


(EJBContext)new InitialContext()
.lookup("java:comp/EJBContext")
HVILE Brugernavn:
SecurityContext.getUserPrincipal()

Returnerer null hvis du ikke er logget ind.

I rolle:
SecurityContext.isUserInRole()
@Context
SecurityContext security;
JSF Brugernavn:
ExternalContext.getUserPrincipal()

Returnerer null hvis du ikke er logget ind.

I rolle:
ExternalContext.isUserInRole()
@Inject
ExternalContext externalContext;


FacesContext.getCurrentInstance()
.getExternalContext()
CDI Brugernavn:
@Inject Principal principal;

Hvis ikke logget ind, injicerer en Principal med getName() == "ANONYMOUS" , svarende til EJB

I rolle: Ikke tilgængelig
@Inject Principal principal;
WebSocket Brugernavn:
Session.getUserPrincipal()

Returnerer null hvis du ikke er logget ind.

I rolle: Ikke tilgængelig
Session videregives som et argument til behandlere af WebSocket-hændelser
XML Web Services Brugernavn:
WebServiceContext.getUserPrincipal()

Returnerer null hvis du ikke er logget ind.

I rolle:
WebServiceContext.isUserInRole()
WebServiceContext kan injiceres i et WS-endepunkt:

@Resource
WebServiceContext wsContext;

Sikkerhedsspecifikationen giver også en oversigt over alle tilgængelige metoder til at hente brugernavn og rolleoplysninger i 4.5. Forholdet til andre specifikationer.

Hvad er den bedste måde?

Jeg vil bestemt anbefale kun at bruge Security API's SecurityContext når det er muligt, af følgende årsager:

  • Det er en samlet API, så du kan lære og huske en enkelt måde at få adgang til brugeroplysninger på
  • Den er nem at bruge, bare injicer den som en CDI-bønne
  • Det giver alle de oplysninger, der leveres af enhver af de andre API'er
  • Det er renere, hvis brugeren ikke er logget – returnerer null Principal i stedet for en Principal med et standardnavn

Den eneste ulempe er, at det i øjeblikket kun virker i Servlet- og EJB-sammenhænge. Selvom disse 2 sammenhænge er de mest udbredte, er det stadig muligt, at sikkerheds-API'en i nogle sjældne tilfælde ikke kan bruges. Forhåbentlig vil de fremtidige versioner af sikkerhedsspecifikationen også dække andre sammenhænge. Og selv hvis ikke, er de sammenhænge, ​​hvor det ikke ville fungere, relateret til nogle ældre og gamle Jakarta API'er og bruges i dag meget sjældent. Faktisk så sjældent, at du sandsynligvis ikke vil bruge nogen af ​​dem nogensinde.

Java tag