bugfix> angular > 投稿

角度コントローラーからRESTコントローラーを使用して、モーダルからデータを送信しようとしています。のPUT、GET、POST メソッド作業コードは、CSRFが不均衡 しかし、私が可能にする CSRF PUTおよびPOSTが機能していません。コンソールログをチェックインすると、405(許可されていないメソッド)

私は一緒にデータを渡す必要があることを知っていますcsrfトークン しかし、角度コントローラーを使用してデータを渡すときにそれを含める方法がわかりません。これは私の最初の角度です。任意の提案は非常に高く評価されています。これが私のコードです。

私の構成:

public class CORSFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type");
        chain.doFilter(req, res);
    }
    public void init(FilterConfig filterConfig) {}
    public void destroy() {}
}

My SecurityConfiguration.java

Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Autowired
    @Qualifier("customUserDetailsService")
    UserDetailsService userDetailsService;
    @Autowired
    PersistentTokenRepository tokenRepository;
    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth)
            throws Exception {
        auth.userDetailsService(userDetailsService);
        auth.authenticationProvider(authenticationProvider());
    }
    /* This method sets-up the list of accessing page for each role. */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // Request Mapping accessible
                .antMatchers("/restUser/**") // -------> HERE I INCLUDE THE REQUEST MAPPING
                // Roles
                .access("hasRole('ADMIN')").and().formLogin()
                .loginPage("/login").loginProcessingUrl("/login")
                .usernameParameter("usernameId").passwordParameter("password").and()
                .rememberMe().rememberMeParameter("remember-me")
                .tokenRepository(tokenRepository).tokenValiditySeconds(86400)
                .and().csrf().and().exceptionHandling()
                .accessDeniedPage("/Access_Denied");
        // Disable spring security
        // http.csrf().disable(); 
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsService);
        authenticationProvider.setPasswordEncoder(passwordEncoder());
        return authenticationProvider;
    }
    @Bean
    public PersistentTokenBasedRememberMeServices getPersistentTokenBasedRememberMeServices() {
        PersistentTokenBasedRememberMeServices tokenBasedservice = new PersistentTokenBasedRememberMeServices(
                "remember-me", userDetailsService, tokenRepository);
        return tokenBasedservice;
    }
    @Bean
    public AuthenticationTrustResolver getAuthenticationTrustResolver() {
        return new AuthenticationTrustResolverImpl();
    }
}

私のRestController:

@RestController
public class UserRestController {
    @Autowired
    UserService userService;
    // -------------------Retrieve All
    // Users--------------------------------------------------------
    @RequestMapping(value = "/restUser", method = RequestMethod.GET)
    public ResponseEntity<List<User>> listAllUsers() {
        List<User> users = userService.findAllUsers();
        if (users.isEmpty()) {
            return new ResponseEntity<List<User>>(HttpStatus.NO_CONTENT);
        }
        return new ResponseEntity<List<User>>(users, HttpStatus.OK);
    }
    // -------------------Create a
    // User--------------------------------------------------------
    @RequestMapping(value = "/restUser", method = RequestMethod.POST)
    public ResponseEntity<Void> createUser(@RequestBody User user,
            UriComponentsBuilder ucBuilder) {
        System.out.println("Creating User " + user.getUsernameId());
        // if (userService.isUserExist(user)) {
        // System.out.println("A User with name " + user.getUsername() +
        // " already exist");
        // return new ResponseEntity<Void>(HttpStatus.CONFLICT);
        // }
        userService.saveUser(user);
        System.out.println("Fetch Data: " + user);
        HttpHeaders headers = new HttpHeaders();
        headers.setLocation(ucBuilder.path("/restUser/{id}")
                .buildAndExpand(user.getId()).toUri());
        return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
    }
    // -------------------Retrieve Single
    // User--------------------------------------------------------
    @RequestMapping(value = "/restUser/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<User> getUser(@PathVariable("id") int id) {
        System.out.println("Fetching User with id " + id);
        User user = userService.findById(id);
        if (user == null) {
            System.out.println("User with id " + id + " not found");
            return new ResponseEntity<User>(HttpStatus.NOT_FOUND);
        }
        System.out.println("Fetch Data: " + user);
        return new ResponseEntity<User>(user, HttpStatus.OK);
    }
    // ------------------- Update a User
    // --------------------------------------------------------
    @RequestMapping(value = "/restUser/{id}", method = RequestMethod.PUT)
    public ResponseEntity<User> updateUser(@PathVariable("id") int id,
            @RequestBody User user) {
        System.out.println("Updating User " + id);
        User currentUser = userService.findById(id);
        //
        // if (currentUser==null) {
        // System.out.println("User with id " + id + " not found");
        // return new ResponseEntity<User>(HttpStatus.NOT_FOUND);
        // }
        // currentUser.setUsernameId(user.getUsernameId());
        // currentUser.setFirstName(user.getFirstName());
        // currentUser.setEmail(user.getEmail());
        System.out.println("USER: " + user);
        userService.updateUser(user);
        return new ResponseEntity<User>(currentUser, HttpStatus.OK);
    }
}

App.js

'user strict';
var App = angular.module('myApp', ['ngResource', 'ngAnimate', 'ui.bootstrap']);

user_service.js

'use strict';

App.factory('User', ['$resource', function ($resource) {
    //$resource() function returns an object of resource class
    return $resource(
            'http://localhost:8080/MavenTry/restUser/:id', 
            {id: '@id'},//Handy for update & delete. id will be set with id of instance
            {
                update: {
                      method: 'PUT' // To send the HTTP Put request when calling this custom update method.
                }
            }
    );
}]);

user_controller.js

'use strict';
App
        .controller(
                'UserController',
                [
                        '$scope',
                        'User',
                        '$uibModal',
                        '$log',
                        function($scope, User, $uibModal, $log) {
                            var self = this;
                            self.user = new User();
                            self.users = [];
                            //Fetch all user data
                            self.fetchAllUsers = function() {
                                self.users = User.query();
                                $log.info('self.users: ', self.users);
                            };
                            // Call function fetchAllUsers                          
                            self.fetchAllUsers();

                            $scope.open = function(id) {
                                $log.info("parameter id: " + id);
                                $scope.items = [];
                                for (var i = 0; i < self.users.length; i++) {
                                    if (self.users[i].id === id) {
                                        self.user = angular.copy(self.users[i]);
                                        $scope.items = angular
                                                .copy(self.users[i]);
                                        break;
                                    }
                                }
                                var modalInstance = $uibModal.open({
                                    templateUrl : 'myModal1',
                                    controller : 'ModalInstance',
                                    size : 'lg',
                                    resolve : {
                                        items : function() {
                                            return $scope.items;
                                        }
                                    }
                                });
                            };
                                self.reset = function() {
                                self.user = new User();
                                $scope.myForm.$setPristine(); // reset Form
                            };
                        } ]);

// Populate modal with data
App.controller('ModalInstance', function($scope, $uibModalInstance, items,
        $log, User) {
    $scope.form = {};
    var myModal = this;
    myModal.user = new User();
    myModal.users = [];
    myModal.fetchAllUsers = function() {
        myModal.users = User.query();
    };
    // Populate DataTable using $GET
    myModal.fetchAllUsers = function() {
        myModal.users = User.query();
        };
    // Create user using $POST
    myModal.createUser = function() {
        myModal.user.$save(function() {
        myModal.fetchAllUsers();
        });
    };
    // Update $PUT
    myModal.updateUser = function() {
            myModal.user.$update(function() {
            myModal.fetchAllUsers();
        });
    };

    $scope.userInfo = items;
    $scope.submitForm = function() {
        if ($scope.form.userForm.$valid) {
            console.log('CSRF_TOKEN', csrftoken); // Here i retrieve the token from the view page. Dont know how to include this while submiting data
            myModal.user = $scope.userInfo;
            // Call function for PUT
            myModal.updateUser();
            $uibModalInstance.close('closed');
        } else {
            console.log('userform is not in scope');
        }
    };
    $scope.cancel = function() {
        $uibModalInstance.dismiss('cancel');
    };
});

//Retrieving CSRF_TOKEN
var csrftoken = (function() {
    var metas = window.document.getElementsByTagName('meta');
    // finding one has csrf token
    for (var i = 0; i < metas.length; i++) {
        if (metas[i].name === "csrf-token") {
            return metas[i].content;
        }
    }
})();
App.constant('CSRF_TOKEN', csrftoken);

私のビューjspでは、csrfトークンを

<meta name="csrf-token" content="${_csrf.token}">

角度コントローラーの私のコードは非常に初心者なので、提案は非常に高く評価されます:)。

回答 2 件
  • このcsrfトークンを取得するには、jQueryまたはプレーンJavaScriptのいずれかを使用します。次に、そのトークンをリソースヘッダーに追加する必要があります。

  • 注:私はOPであり、この答えは実際に問題を解決したものです。

    これを解決するには、SecurityConfigurationクラスに次の行を追加する必要がありました。

    /* This method sets-up the list of accessing page for each role. */
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    // Request Mapping accessible
                    .antMatchers("/restUser/**") // -------> HERE I INCLUDE THE REQUEST MAPPING
                    // Roles
                    .access("hasRole('ADMIN')").and().formLogin()
                    .loginPage("/login").loginProcessingUrl("/login")
                    .usernameParameter("usernameId").passwordParameter("password").and()
                    .rememberMe().rememberMeParameter("remember-me")
                    .tokenRepository(tokenRepository).tokenValiditySeconds(86400)
                    .and().csrf().and().exceptionHandling()
                    .accessDeniedPage("/Access_Denied").and()
                  .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class).csrf().csrfTokenRepository(csrfTokenRepository());
        }    
    private CsrfTokenRepository csrfTokenRepository() {
              HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
              repository.setHeaderName("X-XSRF-TOKEN");
              return repository;
            }
    
    

    CsrfHeaderFilter.classの作成

    public class CsrfHeaderFilter extends OncePerRequestFilter {
        @Override
        protected void doFilterInternal(HttpServletRequest request,
                HttpServletResponse response, FilterChain filterChain)
                throws ServletException, IOException {
            CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
                    .getName());
            if (csrf != null) {
                Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
                String token = csrf.getToken();
                if (cookie == null || token != null
                        && !token.equals(cookie.getValue())) {
                    cookie = new Cookie("XSRF-TOKEN", token);
                    cookie.setPath("/");
                    response.addCookie(cookie);
                }
            }
            filterChain.doFilter(request, response);
        }
    }
    
    

    追加することにより.addFilterAfter(new CsrfHeaderFilter()、CsrfFilter.class).csrf()。csrfTokenRepository(csrfTokenRepository()

    これで、POSTおよびPUTメソッドが機能します。私のコードはそれほどきれいではなく、ベストプラクティスに従うために修正する必要があることを知っています。

    参照:https://spring.io/blog/2015/01/12/the-login-page-angular-js-and-spring-security-part-ii

あなたの答え