Back-End

14 mai, 2013

Dez coisas que você pode fazer com Spring Security

Publicidade

Um

Você pode especificar o provedor de autorização da sua preferência em seu arquivo de configuração XML do Spring. Você pode fazer isso ao configurar authentication-manager como definido no esquema http://www.springframework.org/schema/security/spring-security-3.1.xsd do Spring.

<xs:element name="authentication-manager">
 <xs:complexType>
  <xs:choice minOccurs="0" maxOccurs="unbounded">
   <xs:element name="authentication-provider">
    <xs:complexType>
     <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element ref="security:any-user-service"/>
      <xs:element name="password-encoder">...</xs:element>
     </xs:choice>
     <xs:attributeGroup ref="security:ap.attlist"/>
    </xs:complexType>
   </xs:element>
   <!-- This is BIG -->
   <xs:element name="ldap-authentication-provider">...</xs:element>
  </xs:choice>
  <xs:attributeGroup ref="security:authman.attlist"/>
 </xs:complexType>
</xs:element>

Isso significa, por exemplo, que você pode usar qualquer provedor de autenticação, incluindo autenticação simples e JDBC, como mostrado no snippet abaixo:

<authentication-manager alias="authenticationManager">
  <authentication-provider>
   <user-service>
    <user authorities="ROLE_GUEST" name="guest" password=""/>
   </user-service>
  </authentication-provider>
  <authentication-provider>
   <jdbc-user-service data-source-ref="dataSource"/>
  </authentication-provider>
 </authentication-manager>

Dois

Você pode configurar as regras de autenticação em seu arquivo XML do Spring ao lincar as URLs às regras do usuário utilizando o elemento intercept-url. O elemento intercept-url é um elemento filho do elemento http, cuja definição resumida parece com isto:

<xs:element name="http">
 <xs:complexType>
  <xs:choice minOccurs="0" maxOccurs="unbounded">
   <xs:element name="intercept-url">
    <xs:complexType>
     <xs:attributeGroup ref="security:intercept-url.attlist"/>
    </xs:complexType>
   </xs:element>
   <!-- Details omitted for clarity -->
   <xs:element name="access-denied-handler">...</xs:element>
   <xs:element name="form-login">...</xs:element>
   <xs:element name="openid-login">...</xs:element>
   <xs:element name="x509">...</xs:element>
   <xs:element ref="security:jee"/>
   <xs:element name="http-basic">...</xs:element>
   <xs:element name="logout">...</xs:element>
   <xs:element name="session-management">...</xs:element>
   <xs:element name="remember-me">...</xs:element>
   <xs:element name="anonymous">...</xs:element>
   <xs:element name="port-mappings">...</xs:element>
   <xs:element ref="security:custom-filter"/>
   <xs:element ref="security:request-cache"/>
   <xs:element name="expression-handler">...</xs:element>
  </xs:choice>
  <xs:attributeGroup ref="security:http.attlist"/>
 </xs:complexType>
</xs:element>

Exemplo de uso:

<security:http>
 <security:intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')"/>
 <security:intercept-url pattern="/account/**" access="hasRole('ROLE_USER')" />
 <security:intercept-url pattern="/**" access="hasRole('ROLE_ANONYMOUS')" />
 <!-- other elements removed for clarity -->
</security:http>

Três

Você pode codificar e validar a senha utilizando diversas classes que implementam a interface org.springframework.security.authentication.encoding.PasswordEncoder do Spring. Ela tem apenas dois métodos: encodePassword e isPasswordValid. Suas muitas implementações incluem:

  • BaseDigestPasswordEncoder
  • BasePasswordEncoder
  • LdapShaPasswordEncoder
  • Md4PasswordEncoder,
  • Md5PasswordEncoder
  • MessageDigestPasswordEncoder
  • MessageDigestPasswordEncoder
  • PlaintextPasswordEncoder
  • ShaPasswordEncoder

Quatro

Você pode restringir o acesso a elementos da página utilizando a tag da biblioteca do Spring Security. Para utilizar essa biblioteca, deve incluir a seguinte definição de taglib em seu JSP:

<%@ taglib prefix=”sec” uri=”http://www.springframework.org/security/tags” %>

A taglib contém três tags úteis:

  • authorize
  • authentication
  • accesscontrollist

A mais útil parece ser a tag authorize, que, tomando o exemplo da documentação do Spring, pode ser utilizada de duas formas. Primeiro, você pode autorizar apenas determinados perfis.

<sec:authorize access="hasRole('supervisor')">
This content will only be visible to users who have
the "supervisor" authority in their list of <tt>GrantedAuthority</tt>s.
</sec:authorize>

e autorizar através de URLs

<sec:authorize url="/admin">
This content will only be visible to users who are authorized to send requests to the "/admin" URL.
</sec:authorize>

A URL especificada deve estar amarrada à tag intercept-url descrita no item 2.

Cinco

Você pode realizar autorização no nível de método utilizando as anotações do Spring.

  • @PreAuthorize(“spEL expression”)
  • @PostAuthorize(“spEL expression”)
  • @Secure

onde a expressão spEL pode ser qualquer coisa, mas normalmente é algo como: hasRole(‘ROLE_USER’).

Para permitir @PreAuthorize(…) e @PostAuthorize(…), adicione o seguinte ao arquivo de configuração XML:

<global-method-security pre-post-annotations=”enabled” />

@PreAuthorize(…) é utilizado como mostrado no exemplo a seguir:

 

@PreAuthorize("hasRole('ROLE_ADMIN')")
public void deleteUser(String username);

Para permitir @Secure, adicione o texto a seguir ao arquivo de configuração do Spring:

<global-method-security pre-post-annotations=”enabled” />

 Seis

Você pode realizar segurança pelo nível de método utilizando a implementação JSR-250 do Spring ao acrescentar a configuração seguinte ao arquivo do Spring:

<global-method-security jsr250-annotations=”enabled”/>

As anotações da segurança JSR-250 são um subconjunto das anotações do JSR-250 e incluem:

  • @RolesAllowed({“ROLE_USER”,”ROLE_ADMIN”})
  • @PermitAll
  • @DenyAll

Quando utilizada, a anotação JSR-250 parecem com algo como isso:

@RolesAllowed({"ROLE_ADMIN","ROLE_USER"})
public void deleteUser(String username);

Sete

Você pode integrar o Spring Security com a autenticação OpenID em pouco passos. O primeiro deles é escrever um formulário JSP simples onde o valor de ação está configurado para j_spring_openid_security_check, que, no mínimo, parece com algo deste tipo:

<form action="j_spring-openid-security-check" method="post">
 <label for="openid_idenifier">Login</label>: 
 <input id="openid_identifier" name="openid_identifier" type="text"/>
 <input type="submit" value="Login" />
</form>

O próximo passo é acrescentar o elemento openid-login ao http:

<xs:element name="http">
 <xs:complexType>
  <xs:choice minOccurs="0" maxOccurs="unbounded">
   <xs:element name="openid-login">
    <xs:annotation>
     <xs:documentation>
      Sets up form login for authentication with an
      Open ID identity
     </xs:documentation>
    </xs:annotation>
    <xs:complexType>
     <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded"
       ref="security:attribute-exchange" />
     </xs:sequence>
     <xs:attributeGroup ref="security:form-login.attlist" />
     <xs:attribute name="user-service-ref" type="xs:token">
      <xs:annotation>
       <xs:documentation>
        A reference to a user-service (or
        UserDetailsService bean) Id
       </xs:documentation>
      </xs:annotation>
     </xs:attribute>
    </xs:complexType>
   </xs:element>
   <!-- Other elements omitted for clarity -->
  </xs:choice>
 </xs:complexType>
</xs:element>

Como todos os elementos filhos do openid-login são opcionais, o jeito mais simples de dar permissão ao OpenID é escrever:

<http auto-config="true">
 <openid-login/>
 <!-- other tags and attributes omitted for clarity -->
</http>

Por último, você irá precisar acrescentar o spring-security-openid.jar ao seu projeto.

Oito

Você pode configurar o seu aplicativo para autenticar ao usuários com um servidor LDAP (Lightweight Directory Access Protocol) embutido utilizando a configuração XML. Isso está descrito no esquema XML resumido abaixo:

<xs:element name="ldap-server">
 <xs:complexType>
  <xs:attributeGroup ref="security:ldap-server.attlist" />
 </xs:complexType>
</xs:element>
<xs:attributeGroup name="ldap-server.attlist">
 <xs:attribute name="id" type="xs:token">
  <xs:annotation>
   <xs:documentation>
    A bean identifier, used for referring to the bean elsewhere in the context.
   </xs:documentation>
  </xs:annotation>
 </xs:attribute>
 <xs:attribute name="port" type="xs:positiveInteger"/>
 <xs:attribute name="ldif" type="xs:string">
  <xs:annotation>
   <xs:documentation>
    Explicitly specifies an ldif file resource to load
    into an embedded LDAP
    server. The default is classpath*:*.ldiff
   </xs:documentation>
  </xs:annotation>
 </xs:attribute>
 <xs:attribute name="root" type="xs:string">
  <xs:annotation>
   <xs:documentation>
    Optional root suffix for the embedded LDAP server. Default is
    "dc=springframework,dc=org"
   </xs:documentation>
  </xs:annotation>
 </xs:attribute>
</xs:attributeGroup>

O arquivo LDIF, onde LDIF significa “LDAP Interchange Format”, é um arquivo em formato texto puro utilizado para descrever um conjunto de registros LDAP.

Um exemplo de uso do elemento ldap-server poderia ser:

<ldap-server ldif=”classpath:my-ldif-file.ldif” id=”localserver” />

Para utilizar a integração do LDAP com o Spring Security, lembre-se de incluir o arquivo spring-security-ldap.jar no POM.XML do seu projeto.

Nove

Você pode configurar o seu aplicativo para autenticar usuários com um servidor LDAP remoto utilizando a configuração XML. Isto está descrito no esquema XML exibido abaixo:

<xs:element name="ldap-server">
 <xs:complexType>
  <xs:attributeGroup ref="security:ldap-server.attlist" />
 </xs:complexType>
</xs:element>
<xs:attributeGroup name="ldap-server.attlist">
 <xs:attribute name="id" type="xs:token">
  <xs:annotation>
   <xs:documentation>
    A bean identifier, used for referring to the bean elsewhere 
    in the context.
   </xs:documentation>
  </xs:annotation>
 </xs:attribute>
 <xs:attribute name="url" type="xs:token"/>
 <xs:attribute name="port" type="xs:positiveInteger"/>
 <xs:attribute name="manager-dn" type="xs:string">
  <xs:annotation>
   <xs:documentation>
    Username (DN) of the "manager" user identity which will be used to
    authenticate to a (non-embedded) LDAP server. If omitted, anonymous
    access will be used.
   </xs:documentation>
  </xs:annotation>
 </xs:attribute>
 <xs:attribute name="manager-password" type="xs:string">
  <xs:annotation>
   <xs:documentation>
    The password for the manager DN. This is required
    if the manager-dn is specified.
   </xs:documentation>
  </xs:annotation>
 </xs:attribute>
</xs:attributeGroup>

A documentação afirma que o elemento ldap-server “Define a localização de um servidor LDAP ou inicia um servidor embutido. A url indica a localização do servidor remoto. Se nenhuma url for fornecida, um servidor embutido será iniciado, e ficará escutando no número da porta fornecida. A porta é opcionalm e a porta padrão 33389 é utilizada. O bean LDAP ContextSource do Spring será registrado pelo servidor com o id fornecido”.

Este é o exemplo de uma configuração realmente mínima:

<ldap-server url=”ldap://myServer/dc=captaindebug,dc=com:389″ id=”ldapExternal”

manager-dn=”uid=admin,ou=users,ou=systems” manager-password=”s3cret”/>

Uma vez tendo o servidor configurado, você também precisa configurar o fornecedor da autenticação LDAP. Parece haver vários métodos para fazer isso, e não é algo tão objetivo, portanto, possivelmente falarei mais sobre isso mais tarde…

Dez

Você pode adicionar o atributo requires-channel=”https” ao elemento <intercept-url /> da configuração do Spring Security para forçar qualquer URL que case, para utilizar HTTPS. Por exemplo, se você quiser garantir que a senha será sempre criptografada antes de ser enviada, então você pode adicionar este XML resumido a sua configuração:

<http auto-config="true" use-expressions="true">
    <intercept-url pattern="/login" requires-channel="https"/>
    <!-- Other attributes and elements omitted -->    
</https>

Há algumas outras coisas a serem feitas aqui, mas haverá mais sobre isso mais tarde…

Talvez você tenha percebido que eu utilizei o arquivo de esquema XML do Spring Security (http://www.springframework.org/schema/security/spring-security-3.1.xsd) para explicar alguns dos recursos na minha lista de coisas que você pode fazer com o Spring Security. Em novembro de 2011, escrevi um artigo sobre a anotação @PostConstruct do JSR-250 do Spring que continha um erro (sim, de fato acontece), que foi corretamente apontado pelo Chris Beam – @Cbeam, que deixou um comentário na versão JavaLobby do meu blog. Decidi checar os esquemas e percebi que ambos estavam incorretos (apesar de estar bem mais errado do que o Chris) – o artigo do Captain Debug está agora, até onde sei, correto.

Segurança em aplicativos é um tema complexo e, caso seja alguma coisa que você esteja querendo olhar mais de perto, sugiro adquirir uma cópia do Spring Security 3, de Peter Mularien – que também é recomendado pelo pessoal do Spring.

Finalmente, se há uma ideia importante para apreciar sobre o Spring Security é que, como uma ferramenta de aplicativo, ele permite uma riqueza recursos de ajustes de segurança. Você deveria, portanto, permitir que o Spring Security lidasse com o máximo de detalhes de segurança possível, em vez de desnecessariamente escrever seu próprio código.

***

Artigo traduzido pela Redação iMasters, com autorização do autor. Publicado originalmente em  http://www.captaindebug.com/2012/11/a-list-of-things-you-can-do-with-spring.html#.UX_9REBDs25