Angularjs User Authentication with Java/Jersey Rest API

Asked

Viewed 2,126 times

2

I am developing the user authentication module in my application and I am having some problems accessing the API, getting error 403.

The old way I was doing, when I sent the request to the service, it returned me correctly the data I needed without giving any error (and it still works, because I kept the old controller for comparison). At the time, to make it work, I had to include Corsfilter in the web.config to allow access (since they are different domains).

Now with the new controller, already using some authentication features (I am based on the example of the jasonwatmore), it returns me error 403 as below:

Xmlhttprequest cannot load http://localhost:8081/Gameservice/webserver/usuario/realizaLogin. Response to preflight request doesn’t pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested Resource. Origin 'http://localhost:8080' is therefore not allowed access. The Response had HTTP status code 403.

If I go back to the old controller, it works. If I put in the new it gives the error, even if the same service to be called.

loginController.js (new controller):

    ggApp.controller('loginController', loginController);

    loginController.$inject = ['$location', 'AuthenticationService', 'FlashService'];
    function loginController($location, AuthenticationService, FlashService) {


        var vm = this;
        vm.usuarioLogin = {};

        (function initController() {
            // reset login status
            AuthenticationService.ClearCredentials();
        })();

        this.login = function() {
            var usuario = {
                    email: vm.usuarioLogin.login,
                    senha: vm.usuarioLogin.senha
            }

            vm.dataLoading = true;
            AuthenticationService.Login(usuario, function (response) {
                if (response.success) {
                    AuthenticationService.SetCredentials(usuario);
                    $location.path('/home');
                } else {
                    FlashService.Error(response.message);
                    vm.dataLoading = false;
                }
            });
        };
    }

serviceAutenticacao.js (used only in the new controller):

ggApp.factory('AuthenticationService', AuthenticationService);

    AuthenticationService.$inject = ['$http', '$cookieStore', '$rootScope', '$timeout', 'LoginUsuario'];
    function AuthenticationService($http, $cookieStore, $rootScope, $timeout, LoginUsuario) {
        var service = {};

        service.Login = Login;
        service.SetCredentials = SetCredentials;
        service.ClearCredentials = ClearCredentials;

        return service;

        function Login(usuario, callback) {

            var promise = LoginUsuario.login(usuario); <-- Aqui dá o erro

            promise.$promise.then( 
                function success(response)
                {
                    callback(response);
                });
        }

        function SetCredentials(usuario) {
            var authdata = Base64.encode(usuario.email + ':' + usuario.senha);

            $rootScope.globals = {
                currentUser: {
                    usuario: usuario,
                    authdata: authdata
                }
            };

            $http.defaults.headers.common['Authorization'] = 'Basic ' + authdata; // jshint ignore:line
            $cookieStore.put('globals', $rootScope.globals);
        }

        function ClearCredentials() {
            $rootScope.globals = {};
            $cookieStore.remove('globals');
            $http.defaults.headers.common.Authorization = 'Basic';
        }
    }
....

usuarioController.js (old controller that works):

ggApp.controller("usuarioController", ['$scope', 
                                       'LoginUsuario', 
                                       'Cadastro', 
                                       'VerificaEmail', 
                                       '$location',
                                       function($scope, LoginUsuario, Cadastro, VerificaEmail, $location) {

    $scope.erro = false;
    $scope.mostraMensagem = false;
    $scope.mensagemErro = "teste";
    $scope.classeErro ='alert alert-danger';

    this.usuarioLogin = {};

    $scope.setClasseErro = function() {

        if ($scope.erro) {
            $scope.classeErro ='alert alert-danger'
        } else {
            $scope.classeErro = 'alert alert-success'
        }
    };

    this.realizaLogin = function() {

        var usuario = {
                email: this.usuarioLogin.login,
                senha: this.usuarioLogin.senha
        }

        var promise = LoginUsuario.login(usuario); <--- Mesma Chamada não dá erro!!

        promise.$promise.then( 
                function success(usuario)
                {
                    if (usuario.id > 0) {
                        $location.path("home");
                        $cookieStore.put("autenticado",true);
                    } else {
                        $scope.erro = true;
                        $scope.mensagemErro = "Usuário não encontrado!";
                    };
                    $scope.mostraMensagem = true;
                    $scope.setClasseErro();

                },
                function error(value) {
                    $scope.erro = true;
                    $scope.mostraMensagem = true;
                    $scope.mensagemErro = "Erro: " + value.status;
                }
        );


    };
                                         ....

serviceUsuario.js (service using $resource used by the two controllers, new that accesses through another service and old that accesses directly):

var servicoLogin = angular.module('servicoUsuario', ['ngResource']);

servicoLogin.factory('LoginUsuario', ['$resource',
  function($resource){
    return $resource('http://localhost:8081/GameService/webserver/usuario/realizaLogin', {}, {
      login: {method:'POST'}
    });
  }]);

  }]);

web.xml (server):

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
    <display-name>GamerGaragemService</display-name>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>

    <filter>
        <filter-name>CorsFilter</filter-name>
        <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CorsFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>Jersey Web Application</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>com.gamergaragem.services</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey Web Application</servlet-name>
        <url-pattern>/webserver/*</url-pattern>
    </servlet-mapping>
</web-app>

User resource.java (service class):

@Path("/usuario")
public class UsuarioRecurso {

    private static String persistenceUnitName = "hibernateGG";

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/realizaLogin")
    public UsuarioModel realizarLogin(UsuarioModel usuario){

        SimpleEntityManager simpleEntityManager = new SimpleEntityManager(persistenceUnitName);

        IUsuarioBusiness usuarioB = new UsuarioBusiness(simpleEntityManager);

        Usuario usuarioRetorno = usuarioB.login(usuario.parseTo());

        if (usuarioRetorno != null)
            usuario.parseInto(usuarioRetorno);

        return usuario;
    }
}
  • https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

  • This might help you: http://answall.com/q/86342/132

  • @Victorstafusa I managed to figure out the point of the problem. When I Set a different header in $http.defaults.headers.common.Authorization = 'Basic'; it causes this error. On my server I need to put somewhere saying that it has to accept this type of header?

  • I believe so, yet I can’t say where it would be or what it would be.

  • Colleague your code does not have the Security settings with Spring Security or other. What are you using? The way it is will only work without authentication anyway.

  • @Shura16 lets me see if I understand, to change the header to work with token or other type of authentication I need the server to "understand" this new header, right? I looked for examples to base on, but everything I tried so far gave me the same error. Have any hint/url/tutorial/example to pass me?

Show 1 more comment

1 answer

1

Browser other questions tagged

You are not signed in. Login or sign up in order to post.