Java EE - Argo Navis

Propaganda
Julho/2015
Ja
JavaEE7
SEGURANÇA
helderdarocha
[email protected]
Conteúdo
1. Segurança padrão no Java EE
Mecanismos de segurança em Java SE e Java EE
Terminologia essencial
APIs padrão do Java EE
Passo-a-passo de um cenário típico
2. Segurança em componentes Java EE
Alternativas de autenticação Web
WebServlets, WebFilters, JSF e backing beans
WebSockets
EJB (Session e MessageDriven)
Web Services REST e SOAP
3. Conclusões, alternativas e tendências
O que falta? Alternativas à segurança Java EE
JSR 375 (outra palestra!)
Quem sou eu? Who am I? Кто я?
Helder da Rocha
Tecnologia * Ciência * Arte
Java & Web desde 1995
Autor de cursos e livros
+ de 2500 alunos + de 8000 horas de aula
argonavis.com.br
helderdarocha.com.br
O que é Segurança?
•
•
Safety: proteção contra danos não-intencionais
•
Problemas: bugs em geral e vulnerabilidades intrínsecas
do sistema (threads, ambiente, recursos externos, etc.)
•
Proteção: qualidade da plataforma, boas práticas,
testes, validação, monitoração, logging, checksums, etc.
Security: proteção contra danos intencionais
•
Problemas: ataques em geral, acesso e manipulação de
dados protegidos, danos ao sistema ou a terceiros
•
Proteção: autenticação, autorização, criptografia, auditoria, filtros, auditoria, hashes, etc.
Escopo desta palestra
•
•
Uma visão geral dos recursos de segurança (~ security) da
plataforma Java EE: mecanismos e APIs padrão para
•
Identificação e autenticação de usuários
•
Controle de acesso a dados restritos
•
Controle de execução de operações protegidas
•
Garantias de integridade e confidencialidade para informações que trafegam em rede
Não faz parte do escopo desta palestra
•
Tópicos de segurança não tratados explicitamente nas specs (ex: vulnerabilidades OWASP, governança, auditoria, etc.)
•
Recursos proprietários(WildFly, GlassFish, etc.)
•
Frameworks de terceiros (Spring Security, Seam Security, OAuth, ...)
Mecanismos de segurança
Java SE 8
Segurança nativa da
Plataforma Java
"Sandbox" da JVM
Classloader
Garbage collection
Bytecode verification
Data-typing
+
Criptografia
JCA
JCE
Java XML DSig (JSR 105)
Autenticação
e Autorização
Policy / Security Manager
JAAS
JarSigner TSA/TSP (RFC 3161)
Infraestrutura de
Chave Pública (PKI)
X.509, CRLs e CertPath API
OCSP (RFC 2560)
Comunicação
Segura
JSSE (SSL/TLS)
SASL (RFC 2222)
GSS-API (RFC 2853)
PKCS#11
Mecanismos de segurança
Autenticação
userid
pass / cert
Mensagem
Mensagem
Mensagem
Principal
Conexão
Segura
SSL/TLS
Conexão
Insegura
Role
Role
Autorização
Operações e
Recursos
Camada de Transportes
APIs programáticas: autenticação (JASPIC) e autorização
(JACC + contextos de segurança de cada tipo de componente)
APIs declarativas: autorização, config de autenticação HTTP
(JAAS) e config de transporte SSL/TLS por recurso/método HTTP
Camada de Aplicações
Camada de Aplicações
Java EE 7
na
Autenticação
Camada
& Autorização
Web
Browser
Web Container
Requisição 1: Pede página restrita
GET /app/faces/biblioteca.xhtml
HTTP
Configuração (web.xml)
HTTPS 2-way (CONFIDENTIAL)
Autenticação: jdbc-realm
Métodos: GET, POST
Roles: todos os logados (**)
Resposta 1: Pede credenciais
401 Unauthorized
WWW-Authenticate: Basic realm="jdbc-realm"
HTTPS
HTTPS
Requisição 2: Envia credenciais
GET /app/faces/biblioteca.xhtml Authorization: Basic bWFzaGE6MTIzNDU=
HTTPS
Resposta 2: Envia página restrita
200 OK
Autenticação
Realizar autenticação
Autenticado? Cria credencial.
Ir para Autorização
Não autenticado?
Retorna 401 Unauthorized
Autorização
Verificar permissões
Autorizado?
Retorna recurso pedido
Não autorizado?
Retorna 403 Forbidden
Autorização na
Camada EJB
Web Container
EJB Container
Req2
Contexto EJB (propagados)
Principal: kusko
Roles: {"outro"}
Contexto Web - Credenciais
Principal: kusko
Roles: {"outro"}
Servlet chama metodo 1 em EJB
try {
b.getFigura1();
} catch (EJBAccessException e) {
return "acessonegado.png";
}
Browser
Res2
Servlet chama metodo 2 em EJB
try {
b.getFigura2();
} catch (EJBAccessException e) {
return "acessonegado.png";
}
Autorização
Retornar link
EJBAccessException
@RolesAllowed("**")
public String getFigura1() {
return "peixinho.png";
}
@RolesAllowed("amigo")
public String getFigura2() {
return "lupita.png";
}
Conexão HTTP Segura
•
Pode-se proteger recursos em Java EE configurando a
necessidade do uso de HTTP + camada SSL/TLS
•
SSL/TLS atua na camada de transporte protegendo contra
principais riscos de transferir dados pela rede
•
•
•
Risco de não saber se outro é quem diz que é: autenticação
•
Risco da mensagem ser interceptada e alterada: integridade
•
Risco da mensagem ser interceptada e lida: confidencialidade
SSL/TLS usa vários mecanismos de criptografia
•
Hashes
•
Criptografia de chave pública (assimétrica)
•
Criptografia de chave secreta (simétrica)
Também protege camada de mensagens
mas apenas durante a conexão
User
Rule
Provider
X.509
KeyStore
Principal Grant
Caller Role
Authority
Module
TrustStore
Context
Authentication
Group
Domain
Key
Permission
Realm
Digest
Hash
Certificate
Identity
Trust
Token
Authorization
Subject
Credential
Signature
Policy
Cypher
User
Rule
Provider
X.509
KeyStore
Principal Grant
Caller Role
Authority
Module
TrustStore
Context
Authentication
Group
Domain
Key
Permission
Realm
Digest
Hash
Certificate
Identity
Trust
Token
Authorization
Subject
Credential
Signature
Policy
Cypher
Identificação
•
Quem é você?
•
Segurança depende da identificação dos usuários
(pessoas e sistemas)
•
•
Um nome, um avatar, um endereço IP, um token, ...
Como saber se é autêntico?
^63$t+p@55w0rd#
58:87:52:44:D8:60:12:B0:
FB:D5:F6:C0:6E:F1:6E:FC:
A2:0E:15:8D:58:E9:6E:6F:
76:CE:DA:66:60:B5:9B:C2
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
Autenticação
•
Como provar que você é mesmo você?
•
•
Apresente credenciais: algo que você tem (ex:
documento), é (ex: biometria) ou sabe (ex: senha)
Autenticidade depende de
•
Parecer dado por uma autoridade de confiança
•
Integridade das informações: garantia que os dados
transmitidos não foram alterados pelo caminho)
Realm (~reino, domínio)
•
Autoridade que administra usuários e grupos e que
determina escopo de políticas de segurança (ex: LDAP,
banco de dados, banco de certificados)
•
Também chamado de:
zone
login module
security provider identity manager
domain
identity provider
region
•
identity store
authenticator
auth store
auth repository
auth provider
Java EE utiliza apenas o nome do realm (para selecionar o escopo da autenticação via HTTP)
Usuários (pessoas, máquinas, sistemas)
spock
•
•
masha
vini
kusko
marvin
cerebro
niquel
A criação e autenticação de usuários não faz parte da
especificação Java EE
•
Isto é responsabilidade do realm (que é configurado usando
ferramentas proprietárias - diferente para cada servidor)
•
Java EE apenas padroniza a escolha do método de
autenticação em um realm (se através de cabeçalhos HTTP,
troca de certificados, sessão, etc.)
Java EE não trabalha com usuários, mas com principals
Principal
•
•
Representa uma entidade autenticada
•
java.security.Principal
•
Contém sua identificação (nome / certificado) verificada
através de credenciais
Tem foco diferente em Java SE e Java EE
•
Em Java SE (JAAS) um Subject representa um usuário,
que pode ter uma coleção de identidades (Principal)
•
Em APIs Java EE um Principal representa um usuário,
que pode assumir uma coleção de papéis (Roles)
Autenticação em Java EE
•
•
Java EE oferece duas alternativas (excludentes) de configuração
•
API declarativa na camada Web para selecionar o realm e o método
de autenticação (BASIC, FORM, DIGEST, CLIENT)
•
API programática (JASPIC) para criar módulos de autenticação
A realização da autenticação é dependente de fabricante
•
Maioria oferece APIs e ferramentas proprietárias baseadas em JAAS
web.xml
HttpServletResponse
HttpServletRequest
JASPIC (JSR 196)
javax.security.auth.message
Camada
Web
<login-config>
<auth-method>
BASIC
</auth-method>
<realm-name>
jdbc-realm
</realm-name>
</login-config>
JAAS
java.security.auth
BASIC (RFC 2069 / 2617)
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>jdbc-realm</realm-name>
</login-config>
Browser
configuração
web.xml
Servidor Web
GET /app/secret
401 Unauthorized
WWW-Authenticate: Basic realm="jdbc-realm"
Credenciais: encoding Base64
GET /app/secret
Authorization: Basic bWFzaGE6MTIzNDU=
200 OK
Para fazer logout: feche o browser!
DIGEST (RFC 2069 / 2617)
<login-config>
<auth-method>DIGEST</auth-method>
<realm-name>jdbc-realm</realm-name>
</login-config>
Browser
configuração
web.xml
Servidor Web
GET /app/secret
401 Unauthorized
WWW-Authenticate: Digest realm="jdbc-realm", qop="auth", nonce="143...064", opaque="DF...5C"
GET /app/secret
Authorization: Digest username="masha", realm="jdbc-realm", nonce="143...f89", uri="/app/faces/biblioteca.xhtml", response="2c40...df", opaque="DF...5C", qop=auth, nc=00000001, cnonce="66...948b"
Credenciais: MD5 hash
200 OK
Para fazer logout: feche o browser!
FORM
Browser
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/form.html</form-login-page>
<form-error-page>/erro.html</form-error-page>
</form-login-config>
</login-config>
configuração
web.xml
Servidor Web
GET /app/secret
200 OK Set-Cookie: JSESSIONID=aac...44; Path=/app; Secure; HttpOnly
POST https://localhost:29033/app/faces/j_security_check
Referer: https://localhost:29033/app/faces/biblioteca.xhtml
Cookie: JSESSIONID=aaab5...b1f6
Authorization:Basic Y2VyZWJybzoxMjM0NQ==
<form action="j_security_check" method="POST">
<input type="text" name="j_username">
<input type="password" name="j_password">
<input type="submit">
</form>
Encoding Base64
j_username:masha
j_password:12345
Proteção depende da camada SSL/TLS
200 OK
Para fazer logout: HttpSession#invalidate()
CLIENT-CERT
<login-config>
<auth-method>CLIENT-CERT</auth-method>
</login-config>
Browser
configuração
web.xml
Servidor Web
GET /app/secret
Owner: CN=Self-Signed, OU=Oracle
Corporation, O=Glassfish
Issuer: CN=Self-Signed, OU=Oracle
Corporation, O=Glassfish
Serial number: 3E:56:D0:C9
Valid from: Jul 3 00:12:13 BRT 2015 until:
Jun 30 00:12:13 BRT 2025
Certificate fingerprints:
MD5: F5:A9:21:E3:59:30:E8:...:C3:8C:DE
SHA1: BE:F5:1A:C3:8C:DE:68:...:83:72:A4
SHA256: 1E:2D:F1:96:8B:C2:...:C2:C7:6E
Recebe certificado do servidor
Owner: CN=Helder da Rocha, OU=Argonavis,
O=Argonavis, L=Sao Paulo, ST=SP, C=BR
Issuer: CN=Helder da Rocha, OU=Argonavis,
O=Argonavis, L=Sao Paulo, ST=SP, C=BR
Serial number: 156fb994
Valid from: Tue Jul 14 00:28:45 BRT 2015
until: Mon Oct 12 00:28:45 BRT 2015
Certificate fingerprints:
MD5: F2:B7:23:7B:61:35:D6:...:27:62:7C
SHA1: EC:52:88:9B:4F:63:9D:...:EC:D2:17
SHA256: 2E:35:2B:CF:41:30:...:28:0F:B3
Envia certificado do cliente
200 OK
Configuração é dependente de plataforma
Web Container
javax.servlet
ServletContextListener
contextInitialized()
«create»
javax.security.auth.message.config
*
AuthConfigFactory
javax.security.auth.message.config
AuthConfigProvider
*
JASPIC
*
JSR 196
registerConfigProvider()
«create»
javax.security.auth.message.callback
javax.security.auth.message.config
ServerAuthConfig
«create»
«create»
*
javax.security.auth.message.config
ServerAuthContext
CallbackHandler
javax.security.auth.message.module
ServerAuthModule
HTTP
request
* «create»
initialize()
validateRequest()
validateRequest()
javax.security.auth.message.callback
«create»
javax.security.auth.message.callback
«create»
CallerPrincipalCallback
Register
Principal
and Groups
authenticate
Auth Service
GroupPrincipalCallback
handle()
* Must create implementations of these classes/interfaces
*
Autenticação via
HttpServletRequest
•
API programática (facilita a criação de filtros)
•
getAuthType(): String
•
•
authenticate(HttpServletResponse response)
•
•
Autenticar usando mecanismo configurado
login(String nome, String senha)
•
•
Retorna string com mecanismo de autenticação (BASIC,
DIGEST, FORM, CLIENT-CERT) ou null
Autenticar usando login e senha
logout()
•
Faz com que getRemoteUser(), getCallerPrincipal() e
getAuthType() retorne null
Autenticação com JAX-WS
•
Propriedades padrão JAX-WS para enviar credenciais via
mensagens SOAP em javax.xml.ws.BindingProvider
DungeonWebService service = new DungeonWebService();
Dungeon port = service.getDungeonPort();
Cliente
BindingProvider bp = (BindingProvider)port;
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "https://localhost:29033:/app/dungeon");
bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "masha");
bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "12345");
String secret = port.secretMessage();
@WebService(serviceName = "dungeon")
public class DungeonWebService {
Serviço
@Resource WebServiceContext ctx;
@WebMethod public String secretMessage() {
MessageContext mctx = ctx.getMessageContext();
String user = mctx.get(BindingProvider.USERNAME_PROPERTY);
String pass = mctx.get(BindingProvider.PASSWORD_PROPERTY);
WebSockets Seguro
http://localhost/app/inseguro
HTTP
(JavaScript)
new WebSocket( ws://localhost/app/endpoint )
WebSocket estabelecido
new WebSocket( wss://localhost/app/endpoint )
401 Unauthorized
https://localhost/app/seguro
HTTP SSL
new WebSocket( wss://localhost/app/endpoint )
WebSocket estabelecido
new WebSocket( ws://localhost/app/endpoint )
SecurityError
(JavaScript)
User
Rule
Provider
X.509
KeyStore
Principal Grant
Caller Role
Authority
Module
TrustStore
Context
Authentication
Group
Domain
Key
Permission
Realm
Digest
Hash
Certificate
Identity
Trust
Token
Authorization
Subject
Credential
Signature
Policy
Cypher
Autorização
•
Como controlar o acesso a recursos protegidos?
•
Quem pode acessar?
•
Quais recursos? URLs, componentes, classes, métodos,
blocos de código, tabelas, registros, fragmentos de XML,
imagens, arquivos, pastas, aplicações
•
Que ações podem executar? GET, POST, ler, gravar,
criar, remover
•
Quais condições? "das 9 as 17h", "enquanto houver tokens", "apenas duas vezes"
Este tipo de controle
de acesso não existe
em Java EE 7
Grupos (~coleções de usuários no servidor)
•
masha
Usuários podem pertencer a grupos
•
Mas usuários não fazem parte do escopo do
Java EE, e grupos também não
•
Conceito é dependente de plataforma
megalomaniacos
marvin
terraqueos
marvin
ratos
cerebro
alienigenas
spock
Grupos criados para
aplicação exemplo no
Glassfish 4.1
cerebro
masha
russos
masha
niquel
masha
vini
cerebro
niquel
vini
kusko
Roles (~chaves de acesso a recursos protegidos)
•
Principals (grupos e usuários) devem ser mapeados a roles
•
Mapeamento é proprietário: Não há padrão em Java EE
•
Definição de grupos, roles, realms, etc. varia entre fornecedores
Exemplo de mapeamentos possíveis em Glassfish 4.1
role: administrador
- grupo alienigenas
- usuário cerebro
alienigenas
role: especial
- usuário vini
- usuário masha
role: amigo
- usuário vini
- usuário masha
- usuário niquel
role: outro
- usuário kusko
Aplicação: JavaEESecurity.war (veja código-fonte)
<glassfish-web-app>
<context-root>JavaEESecurity</context-root>
<security-role-mapping>
<role-name>administrador</role-name>
<principal-name>cerebro</principal-name>
<group-name>alienigenas</group-name>
</security-role-mapping>
<security-role-mapping>
<role-name>especial</role-name>
<principal-name>vini</principal-name>
<principal-name>masha</principal-name>
</security-role-mapping>
<security-role-mapping>
<role-name>amigo</role-name>
<principal-name>masha</principal-name>
<principal-name>vini</principal-name>
<principal-name>niquel</principal-name>
</security-role-mapping>
<security-role-mapping>
<role-name>outro</role-name>
<principal-name>kusko</principal-name>
</security-role-mapping>
</glassfish-web-app>
/WEB-INF/glassfish-web.xml
Autorização em Java EE
•
Baseada em roles, fácil de usar e 100% Java EE*
•
Configuração declarativa via anotações e deployment
descriptor XML, ou através de API programática (JACC)
•
Acesso (leitura) através APIs programáticas em
contextos de segurança
Camada EJB
Camada Web
Anotações
@ServletSecurity(
@HttpConstraint(
transportGuarantee = ...,
rolesAllowed = {...}
)
)
public class MyServlet... {...}
@RolesAllowed({...})
public class Bean {...
@DenyAll public void m1() {}
@PermitAll public void m2() {}
Deployment descriptors
<security-constraint>
web.xml
<web-resource-collection>
...
</web-resource-collection>
<auth-constraint>
<role-name>...</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>...</transport-guarantee>
</user-data-constraint>
</security-constraint>
<method-permission>
<role-name>...</role-name>
<method>
<ejb-name>...</ejb-name>
<method-name>...</method-name>
</method>
</method-permission>
ejb-jar.xml
JACC (JSR 115)
java.security
Permission
javax.security.jacc
WebResourcePermission
javax.security.jacc
WebRoleRefPermission
javax.security.jacc
WebUserDataPermission
javax.security.jacc
EJBRoleRefPermission
javax.security.jacc
EJBMethodPermission
* depois de mapeados grupos/usuários a roles
Autorização em web.xml
•
É preciso declarar os roles no web.xml usando
<security-role> (em servlets pode ser via anotações).
•
Mapeamento dos roles com usuários/grupos é
dependente de servidor (glassfish-web.xml, jboss-web.xml, etc.)
<web-app> ...
<security-role>
<role-name>administrador</role-name>
</security-role>
<security-role>
<role-name>amigo</role-name>
</security-role>
<security-role>
<role-name>especial</role-name>
</security-role>
...
</web-app>
Security constraints
•
Bloco <security-constraint> contém três partes
•
Um ou mais <web-resource-collection>
•
Pode conter um <auth-constraint> (lista de roles)
•
Pode conter um <user-data-constraint> (SSL/TLS)
<security-constraint>
<web-resource-collection>
<web-resource-name>Área restrita</web-resource-name>
<url-pattern>/secreto/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>administrador</role-name>
</auth-constraint>
</security-constraint>
Web resource collection
•
Agrupa recursos e operações controladas através de
padrões de URL + métodos HTTP
•
•
Métodos HTTP não informados são restritos, mas métodos
não informados estão descobertos
Use <deny-uncovered-http-methods/> ou outro bloco
negando acesso a todos exceto <http-method-omission>
<security-constraint>
<web-resource-collection>
<web-resource-name>Área restrita</web-resource-name>
<url-pattern>/secreto/*</url-pattern>
<url-pattern>/faces/castelo.xhtml</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
...
</security-constraint>
Authorization constraint
•
Com <auth-constraint> as <web-resource-collection>
são acessíveis apenas aos <role-name> declarados
•
Sem <auth-constraint>: sem controle de acesso (livre)
•
<auth-constraint /> vazio: ninguém tem acesso
<web-app>
...
<security-constraint>
<web-resource-collection> ... </web-resource-collection>
<web-resource-collection> ... </web-resource-collection>
<auth-constraint>
<role-name>administrador</role-name>
<role-name>especial</role-name>
</auth-constraint>
</security-constraint>
...
<security-constraint> ....</security-constraint>
</web-app>
Transport guarantee
•
Garantias mínimas para comunicação segura SSL/TLS
•
NONE: (ou ausente) não garante comunicação segura
•
INTEGRAL: proteção integral, autenticação no servidor
•
CONFIDENTIAL: proteção integral, autenticação: cliente e servidor
<web-app> ...
<security-constraint>
...
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<security-constraint>
...
<user-data-constraint>
<transport-guarantee>INTEGRAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
</web-app>
Servlet 3.x @ServletSecurity
@WebServlet(name = "ServletSecreto", urlPatterns = {"/secreto"})
@ServletSecurity(
@HttpConstraint(
transportGuarantee = TransportGuarantee.CONFIDENTIAL,
rolesAllowed = {"amigo", "administrador"}
)
)
public class ServletSecreto extends HttpServlet { ... }
@WebServlet(name = "LabirintoServlet", urlPatterns = {"/labirinto"})
@ServletSecurity(httpMethodConstraints={
@HttpMethodConstraint("GET"),
@HttpMethodConstraint(value="POST", rolesAllowed={"outro"}),
@HttpMethodConstraint(
value="TRACE",
transportGuarantee = TransportGuarantee.NONE,
rolesAllowed = {"amigo", "administrador"}
)
})
public class LabirintoServlet extends HttpServlet { ... }
Autorização com HTTPServletRequest
•
Acesso via API a principal e roles permitem controle
programático da autorização
•
getUserPrincipal()
•
•
Obtém java.security.Principal (getName() obtém nome)
isUserInRole("role")
•
Testa se o usuário autenticado faz parte do role
String loggedUser = request.getUserPrincipal().getName();
if( !request.isCallerInRole("administrador")) {
if (!loggedUser.equals("cerebro")) {
throw new SecurityException("...");
}
}
Autorização em JSF e CDI
•
Através de request
<h:panelGroup rendered="#{request.userPrincipal == 'masha'}">
<p>Conteúdo visto pelo usuário masha</p>
</h:panelGroup>
<h:panelGroup rendered="#{request.isUserInRole('especial')}">
<p>Conteúdo visto por quem possui o role especial</p>
</h:panelGroup>
•
No Managed Bean pode-se usar ExternalContext
ExternalContext ctx = FacesContext.getCurrentInstance().getExternalContext();
boolean inRole = ctx.isUserInRole("role");
String user
= ctx.getUserPrincipal().getName();
•
Ou injetar o Principal via CDI
@Inject java.security.Principal;
Autorização em WebSockets
•
Contexto de segurança em javax.websocket.Session
retorna apenas o java.security.Principal
@ServerEndpoint("/secretpoint")
public class SecretEndPoint {
@OnMessage
public void onMessage(String message, Session session) {
String user = session.getUserPrincipal().getName();
...
}
}
•
É possível redefinir o WebSocket Handshake para passar
outros dados de contexto via HttpServletRequest
Autorização em EJB
@DeclareRoles({"amigo", "administrador"})
@Stateless public class ImagemBean {
@RolesAllowed("administrador")
public void removerUsuario(Usuario u) { ... }
@RolesAllowed("amigo")
public List<Usuario> listaDeUsuarios() { ... }
@PermitAll
public String getInfo() { ... }
@RolesAllowed("**")
public String getFreeStuff() { ... }
@DenyAll
public String loggingData() { ... }
}
Segurança em ejb-jar.xml
•
Raramente usado por desenvolvedores (já que toda a
segurança pode ser configurada por anotações)
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" ... >
<enterprise-beans>
<session>
<ejb-name>testeBean</ejb-name>
<ejb-class>testebean.TesteBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
<assembly-descriptor>
<security-role>
<role-name>administrador</role-name>
</security-role>
<method-permission>
<role-name>administrador</role-name>
<method>
<ejb-name>testeBean</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
...
</assembly-descriptor>
</ejb-jar>
Propagação de identidade
•
@RunAs("role")
•
Declarado antes da declaração de classe permite que o
componente execute usando um role específico
•
Permite que componente tenha um role mesmo que não tenha
sido propagado pelo container cliente
@MessageDriven
@RunAs("administrador")
public class TestEJB { ... }
O container confia
na identidade
propagada (não
autentica de novo)
<message-driven>
<ejb-name>TestEJB</ejb-name>
<ejb-class>br.com.ejb.examples.TestEJB</ejb-class>
<security-identity>
<run-as>
<role-name>administrador</role-name>
</run-as>
</security-identity>
</message-driven>
Autorização com EJBContext
•
Métodos de javax.ejb.EJBContext
•
•
Herdados por SessionContext e MessageDrivenContext
Mesmos métodos, mas com nomes diferentes
•
Caller no contexto EJB é o User no contexto Web
String loggedUser = ctx.getCallerPrincipal().getName();
if( !ctx.isCallerInRole("administrador")) {
if (!loggedUser.equals("cerebro")) {
throw new EJBAccessException("...");
}
}
Autorização em JAX-RS
•
Resources são EJBs, portanto podem usar
mesmos mecanismos de autorização declarativos
@Stateless @Path("usuario")
@RunAs("administrador")
public class UsuarioFacadeREST {
@DenyAll
@POST @Consumes({"application/xml", "application/json"})
public void create(Usuario entity) { ...
}
@RolesAllowed({"administrador"})
@PUT @Path("{id}") @Consumes({"application/xml", "application/json"})
public void edit(@PathParam("id") Integer id, Usuario entity) { ...
} ...
}
API de segurança em JAX-RS
•
Aproveita mesmo ambiente do contexto Web
•
Métodos de javax.ws.rs.core.SecurityContext
•
getAuthenticationScheme()
•
•
isSecure()
•
•
Retorna true se a requisição foi feita em canal seguro
getUserPrincipal()
•
•
Retorna o string contendo o esquema de autenticação (mesmo
que HttpServletRequest#getAuthType())
Retorna java.security.Principal com usuário autenticado
isUserInRole(String role)
•
Retorna true se usuário autenticado pertence ao role
API de segurança em JAX-WS
•
Mecanismos declarativos de autorização
aproveitam a estrutura do contexto Web
(<security-constraint>)
•
API programática de segurança mínima em
javax.xml.ws.WebServiceContext
•
•
getUserPrincipal()
•
isUserInRole("role")
Suporte a criptografia na camada de mensagens (ainda) não faz parte do Java EE
Como obter principals e testar roles
em Java EE 7
WebServlets,
Facelets, WebFilters
getUserPrincipal()
EJBs
getCallerPrincipal()
isCallerInRole()
isUserInRole()
javax.servlet.http.
HttpServletRequest
JSF backing beans
getUserPrincipal()
javax.ejb.
EJBContext
getUserPrincipal()
isUserInRole()
javax.xml.ws.
WebServiceContext
CDI
@Inject java.security.Principal
isUserInRole()
WebSockets
javax.faces.context.
ExternalContext
SOAP Web Services
getUserPrincipal()
javax.websocket.
Session
RESTful Web Services
getUserPrincipal()
isUserInRole()
javax.ws.rs.core.
SecurityContext
O que falta em Java EE?
•
Ter uma API padrão de segurança moderna, unificada e
independente de fabricante
•
•
•
Segurança Java EE hoje, na prática, usa recursos proprietários ou
frameworks de terceiros (Spring, etc.)
O que mais?
•
Terminologia comum (callers/users, groups/roles, identity store)
•
Contexto de segurança acessível de qualquer componente
•
Mecanismo de autenticação mais flexível , independente de servidor
e com implementações padrão
•
APIs padronizadas para identity stores (não depender de realms
proprietários)
•
Formas de controlar acesso além de roles (regras, interceptadores)
Como será o futuro da segurança em Java EE?
To be continued...
Hoje, 17:40
Referências (1/3)
Documentação oficial
•
Eric Jendrock et al. The Java EE 7 Tutorial, Release 7 (Oracle, September 2014). http://docs.oracle.com/javaee/7/tutorial/ O capítulo 50 contém um tutorial sobre Segurança em Java
EE com Glassfish (os exemplos e as configurações funcionam apenas no Glassfish).
•
Oracle. Java SE Security. http://www.oracle.com/technetwork/java/javase/jaas/index.html Uma visão geral das APIs Java SE de segurança.
•
Oracle. JAAS Authentication tutorial. http://docs.oracle.com/javase/8/docs/technotes/guides/security/jaas/tutorials/GeneralAcnOnly.html
•
Oracle. JAAS Authorization tutorial. http://docs.oracle.com/javase/8/docs/technotes/guides/security/jaas/tutorials/GeneralAcnAndAzn.html
•
Oracle. Java Security Overview. http://docs.oracle.com/javase/8/docs/technotes/guides/security/overview/jsoverview.html
Java EE 8
•
Alex Kosowski. Finally EE Security API JSR 375. Devoxx France 2015. http://pt.slideshare.net/a_kosowski/devoxx-fr-ee8jsr375securityapiv1
•
JSR 375 Java EE Security API. https://www.jcp.org/en/jsr/detail?id=375 Página do JSR aberto em dezembro 2014.
Referências (2/3)
Especificações Java EE http://www.oracle.com/technetwork/java/javaee/tech/index.html
•
Ron Monzillo. Java Authentication SPI for Containers JSR 196, Version 1.1, Oracle, 2013
•
Ron Monzillo. Java Authorization Contract for Containers JSR 115, Version 1.5, Oracle, 2013
•
Shing Wai Chan e Rajiv Mordani. Java Servlet Specification, Version 3.1, Chapter 13: Security,
Oracle, 2013
•
Marina Vatkina. JSR 345 Enterprise JavaBeans, Version 3.2. EJBCore Contracts and Requirements.
Chapter 12 Security Management. Oracle, 2013.
•
Danny Coward. Java API for WebSocket. Version 1.0. Chapter 8: Server Security. Oracle, 2013
•
Jitendra Kotamraju. WebServices for Java EE, Version 1.3. Chapter 9: Security. Sun, 2009.
•
Jitendra Kotamraju. The Java API for XML-Based Web Services (JAX-WS) 2.2 Rev. a. Section 4.2.2.1
(Standard properties). Oracle, 2011.
•
Santiago Pericas-Geertsen e Marek Potociar. JAX-RS: Java API for RESTful Web Services. Version
2.0. Section 9.2.5 Security Context. Oracle, 2013
•
Pete Muir et al. Contexts and Dependency Injection for Java EE, Version 1.1. Section 3.8 (Additional
built-in beans). Oracle, 2013.
Livros
•
Arun Gupta. Java EE 7 Essentials O'Reilly, 2013. Código-fonte com vários exemplos usando recursos de segurança em Java EE 7: https://github.com/javaee-samples/javaee7-samples
Referências (3/3)
Artigos e apresentações sobre Java EE 7
•
Marian Muller. “Please Log In”: Authentication and Authorization in Java SE and Java EE.
JavaONE 2013. https://www.youtube.com/watch?v=pBDqIavwMYw
Tutorial (video) sobre recursos de segurança em Java SE e Java EE, cobrindo JAAS e JASPIC.
•
Arjan Tijms. Implementing container authentication in Java EE with JASPIC Nov/2012. http://arjan-tijms.omnifaces.org/2014/03/implementing-container-authorization-in.html
Tutorial abrangente sobre JASPIC 1.0 (veja também posts do autor sobre JACC).
•
Ron Monzillo. Using JACC to determine a caller's roles. Ron Monzillo's Weblog. Aug 18 2008.
https://blogs.oracle.com/monzillo/entry/using_jacc_to_determine_a
Aplicações práticas de alguns recursos da API JACC.
•
Ron Monzillo. Adding Authentication Mechanisms to the GlassFish Servlet Container. Ron
Monzillo's Weblog. Apr 30, 2008. https://blogs.oracle.com/enterprisetechtips/entry/adding_authentication_mechanisms_to_the Um tutorial de JASPIC.
Produtos, extensões e alternativas
•
Bauke Sholtz. Apache Shiro. Is it ready for Java EE 6? The BalusC Code, Janeiro/2013. http://balusc.blogspot.com.br/2013/01/apache-shiro-is-it-ready-for-java-ee-6.html
•
Social Auth. https://code.google.com/p/socialauth/ Ferramenta de extensão para autenticação usando CAS, OAuth, OpenID.
•
Seam Security. http://docs.jboss.org/seam/3/security/latest/reference/en-US/html_single/ Alternativa à segurança padrão Java EE.
•
Spring Security. http://projects.spring.io/spring-security/
Alternativa à segurança padrão Java EE.
2015
obrigado!
[email protected]
Palestra
http://www.argonavis.com.br/download/tdc_2015_javaee7security.html
Código-fonte
https://github.com/argonavisbr/JavaEE7SecurityExamples
Download