角度コントローラーから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}">
角度コントローラーの私のコードは非常に初心者なので、提案は非常に高く評価されます:)。
注:私は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
関連記事
- AngularJSのコントローラーの基本を理解する
- @ HtmlCheckboxforがクリックされたときにコントローラーにデータを送信する方法
- AngularJS:コントローラーの工場:$httpgetから値を取得していない
- wtfは、フィールドではなく、トークンのみの送信時に検証します
- アンギュラーjs:コントローラーからng-model値を更新しますか?
- コントローラ変数値をAngularJSのディレクティブに渡します
- HTMLフォームからコントローラーに日付を送信する
- 送信しないボタンとしてボタンタイプを使用して、ボタン値をコントローラーmvcに渡します
- Node-RedはAngularJSコントローラーを登録できません
このcsrfトークンを取得するには、jQueryまたはプレーンJavaScriptのいずれかを使用します。次に、そのトークンをリソースヘッダーに追加する必要があります。