OAuth com Facebook e Java

Caros,

Depois de muito bater cabeça e muitos tutoriais depois, consegui criar um projeto que utiliza o protocolo OAuth e a API do Facebook para efetuar login em uma aplicação Web. Curtam o tutorial.

O que eu utilizei:

  • Netbeans 7.1.2
  • Java 7
  • Facebook-api-3.0.4
  • Primefaces 3.3.1
  • RestFb 1.6.9
  • Maven
  • Glassfish 3.1.2
  • JSF 2

Passo 1.

Crie um projeto web Maven através do menu: Arquivo -> Novo Projeto -> Maven -> Aplicação Web. Siga os passos selecionando o Glassfish e afins (não entrarei no cerne da criação de um projeto web).

Passo 2.

Edite o arquivo pom.xml adicionando os seguintes repositórios e dependências:


<repositories>
<repository>
<id>prime-repo</id>
<name>PrimeFaces Maven Repository</name>
<url>http://repository.primefaces.org</url>
<layout>default</layout>
</repository>
</repositories>


<dependencies>
<dependency>
<groupId>com.restfb</groupId>
<artifactId>restfb</artifactId>
<version>1.6.9</version>
</dependency>
<dependency>
<groupId>com.google.code.facebookapi</groupId>
<artifactId>facebook-java-api</artifactId>
<version>3.0.4</version>
</dependency>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>freemaker</groupId>
<artifactId>freemaker</artifactId>
<version>2.3.8</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>br.com.xpert</groupId>
<artifactId>xpertframework</artifactId>
<version>1.0.7</version>
</dependency>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-api</artifactId>
<version>2.10</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>3.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
</dependencies>

Passo 3. Crie uma Classe chamada UsuarioFB, essa classe irá armazenar os dados provindos do Facebook:


public class Usuario {

@Facebook
private String id;
@Facebook
private String name;
@Facebook
private String email;

A Anotação @Facebook provém do RestFB, um biblioteca que encontrei nas minhas pesquisas na web e muito me ajudou. Mais informações em: RestFB.com

Passo 4. Crie um ManagedBean que irá gerenciar o usuário logado da aplicação:


@ManagedBean
@SessionScoped
public class LoginController {

private String login;
private String senha;
private Usuario usuario;

Observação!!! Nunca se esqueça de implementar os métodos getters e setters!!!

Passo 4. Configure sua aplicação no Facebook, para isso acesse o link: Facebook Developers. Tutorial bom: Tutorial Configuração Aplicação. Esse passo irá gerar uma API_KEY e uma API_SECRET.

Passo 5. Crie um Classe chamada FaceBookClient que irá gerir os métodos de conexão e obtenção do token de acesso:


public class FaceBookClient {

public static String API_KEY = “SUA API KEY”;
public static String SECRET = “SUA API SECRET”;
private static final String client_id = “SEU CLIENT ID”;
// set this to your servlet URL for the authentication servlet/filter
private static final String redirect_uri = “SUA URL DE RETORNO (pode ser o locahost)”;
/// set this to the list of extended permissions you want
private static final String[] perms = new String[]{“publish_stream”, “email”};

public static String getAPIKey() {
return API_KEY;
}

public static String getSecret() {
return SECRET;
}

public static String getLoginRedirectURL() {
return “https://graph.facebook.com/oauth/authorize?client_id=&#8221;
+ API_KEY + “&display=page&redirect_uri=”
+ redirect_uri + “&scope=publish_stream, email”;
}

public static String getAuthURL(String authCode) {
return “https://graph.facebook.com/oauth/access_token?client_id=&#8221;
+ API_KEY + “&redirect_uri=”
+ redirect_uri + “&client_secret=” + SECRET + “&code=” + authCode;
}

Passo 6. Implementaremos agora um Filter que irá receber a resposta do Facebook.


public class FacebookFilter implements Filter {

@Override
public void init(FilterConfig filterConfig) throws ServletException {
}

@Override
public void doFilter(ServletRequest sr, ServletResponse sr1, FilterChain fc) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) sr;
HttpServletResponse res = (HttpServletResponse) sr1;
String code = sr.getParameter(“code”);

if (code != “”) {
String authURL = FaceBookClient.getAuthURL(code);
URL url = new URL(authURL);
try {
String result = readURL(url);
String accessToken = null;
Integer expires = null;
String[] pairs = result.split(“&”);
for (String pair : pairs) {
String[] kv = pair.split(“=”);
if (kv.length != 2) {
throw new RuntimeException(“Unexpected auth response”);
} else {
if (kv[0].equals(“access_token”)) {
accessToken = kv[1];
}
if (kv[0].equals(“expires”)) {
expires = Integer.valueOf(kv[1]);
}
}
}
if (accessToken != null && expires != null) {

Usuario u = new Usuario();
UsuarioService us = new UsuarioService();
us.authFacebookLogin(accessToken, expires);
res.sendRedirect(“AQUI COLOQUE A URL DE RETORNO depois do login, por exemplo: http://localhost:8080/LoginFacebook/logado.jsf&#8221;);
} else {
throw new RuntimeException(“Access token and expires not found”);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

private String readURL(URL url) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = url.openStream();
int r;
while ((r = is.read()) != -1) {
baos.write(r);
}
return new String(baos.toByteArray());
}

@Override
public void destroy() {
}
}

Passo 7. Configure o Filter no web.xml:

<filter>
<filter-name>FacebookFilter</filter-name>
<filter-class>br.com.estudos.filter.FacebookFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>FacebookFilter</filter-name>
<url-pattern>/login/*</url-pattern>
</filter-mapping>

Passo 8. Implementemos agora o método que efetua o login no ManagedBean, adicione o seguinte código no ManagedBean:

public String conectarComFace() {
return FaceBookClient.getLoginRedirectURL();
}

Passo 9. Perceba que na configuração do Filter colocamos para ele atuar em um diretório chamado login, isso força nossa implementação a url de redirecionamento (configurada no passo 5) ser redirecionada para uma página dentro desse diretório. Portanto, crie esse diretório na sua aplicação.

Passo 10. Crie as páginas para efetuar o Login que deve conter um commandLink:

<h:outputLink value=”#{loginController.conectarComFace()}”>
Login com FaceBook
</h:outputLink>

A página logado (como configurado no passo 6) contém apenas a palavra `Logado`.

Passo 11. Criaremos um UsuarioService, reponsável pela consulta dos dados do usuário:


public class UsuarioService {

public void authFacebookLogin(String accessToken, int expires) {
try {

FacebookClient fb = new DefaultFacebookClient(accessToken);

Usuario user = fb.fetchObject(“me”, Usuario.class);

System.out.println(user);

} catch (Throwable ex) {
throw new RuntimeException(“failed login”, ex);
}
}
}

O código do exemplo está aqui: LoginFacebook!

Enjoy!

Agendamento de Tarefas no Spring

Olá Senhores,

Outro dia me deparei com um problema, precisava que minha aplicação enviasse um email para o administrador de tempos em tempos sem interferência de qualquer evento.

Pois bem, foi quando eu conheci o Quartz, como ele o Spring Framework pode agendar tarefas com facilidade.

Para definir um agendamento, todo o trabalho é praticamente feio na configuração do applicationContext.xml do Spring.

Cria-se uma Session Bean que contém o método que será executado.

<bean id=”emailAction”

scope=”prototype” c

lass=”br.acoes.EmailAction”>

Em seguida, utiliza-se a classe MethodInvokingJobDetailFactoryBean para definir qual dos beans possui a tarefa e quais de seus métodos será executado:

<bean id=”quartzEmail” class=”org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean”>

<property name=”targetObject” ref=”emailAction”/>

<property name=”targetMethod” value=”enviar”/>

</bean>


Deve ser criado um temporizador para que o Quarzt saiba de quanto em quanto tempo ele será acionado, existem duas formas para se definir isso:

Simple trigger – Um agendador de tarefas simples, que será executado no intervalo de tempo definido em milisegundos (repeatInterval), possuindo um tempo de execução inicial (startDelay).

<bean id=”simpleTrigger” class=”org.springframework.scheduling.quartz.SimpleTriggerBean”>

<property name=”jobDetail” ref=”quartzEmail” />

<property name=”startDelay” value=”1″ />

<property name=”repeatInterval” value=”9000″ />

</bean>

Cron trigger – A tarefa pode ser executada em inúmeras configurações como por exemplo toda quinta as 19:00.  Para detalhes dessa configuração visite o site oficial.

<bean id=”cronTrigger” class=”org.springframework.scheduling.quartz.CronTriggerBean”>

<property name=”jobDetail” ref=”quartzEmail” />

<property name=”cronExpression” value=”0 0 21* * ?” />

</bean>

O último passo é definir o SchedulerFactoryBean com a lista dos detalhes de tarefa que devem ser executados:

<bean class=”org.springframework.scheduling.quartz.SchedulerFactoryBean”>

<property name=”triggers”>

<list>

<ref bean=”cronTrigger” />

</list>

</property>

</bean>

Com essas configurações, o método envia() da classe EmailAction será executado todo dia as 21 horas.

Abração

Enjoy!