web-dev-qa-db-ja.com

Spring Securityは常に403を禁止し、アクセスは拒否されました

管理者が管理者ページにアクセスできるようにし、管理者ができるようにしたいのですが、/ admin/**のURLにロールadminのユーザーのみがアクセスできるように設定してそれを行おうとすると、403 Forbidden、access deniedが返されます。しかし、ユーザーには、チェックしたROLE_ADMINに設定された権限があります。私は何を間違えていますか?

ユーザーログイン用のマイコントローラー

_@RestController
public class UserController {

    @Autowired
    AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private AuthorityService authorityService;

    @Autowired
    private UserAuthorityService userAuthorityService;

    @Autowired
    TokenUtils tokenUtils;

    @Autowired
    private UserService userService;

    @RequestMapping(value = "/api/login", method = RequestMethod.POST, produces = "text/html")
    public ResponseEntity<String> login(@RequestBody LoginDTO loginDTO) {
        try {
//          System.out.println(loginDTO.getUsername() + " " + loginDTO.getPassword());
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
                    loginDTO.getUsername(), loginDTO.getPassword());

            Authentication authentication = authenticationManager.authenticate(token);

            SecurityContextHolder.getContext().setAuthentication(authentication);

            UserDetails details = userDetailsService.loadUserByUsername(loginDTO.getUsername());

            return new ResponseEntity<String>(tokenUtils.generateToken(details), HttpStatus.OK);
        } catch (Exception ex) {
            return new ResponseEntity<String>("Invalid login", HttpStatus.BAD_REQUEST);
        }
    }

    @RequestMapping(value = "/api/register", method = RequestMethod.POST, produces = "text/html")
    public ResponseEntity<String> register(@RequestBody RegisterDTO registerDTO) {
        try {
            System.out.println(registerDTO);
            User user = userService.findUserByUsername(registerDTO.getUsername());
//            // Check if user with that username exists
            if(user != null){
                // User with that username is found
                return new ResponseEntity<String>("User with that username exists", HttpStatus.BAD_REQUEST);
            }
            // We need to save the user so his ID is generated
            User newUser = userService.saveUser(new User(registerDTO));

            UserAuthority userAuthority = userAuthorityService.save(new UserAuthority(newUser, authorityService.findOneByName("User")));

            Set<UserAuthority> authorities = new HashSet<>();
            authorities.add(userAuthority);

            newUser.setUserAuthorities(authorities);
            User savedUser = userService.save(newUser);
            return new ResponseEntity<String>("You have registered successfully with username " + savedUser.getUsername(), HttpStatus.OK);
        } catch (Exception ex) {
            return new ResponseEntity<String>("Invalid register", HttpStatus.BAD_REQUEST);
        }
    }
}
_

私は郵便配達員でアプリをテストし、ログインと登録はうまく機能していると言えます。ユーザーがログインすると、正しいデータとユーザー権限でトークンを取得できますが、なぜ/ admin/building/add urlにアクセスしようとすると403エラーが返されますか?

管理ページのビルドを追加するためのコントローラー:

_@RestController
public class BuildingController {

    @Autowired
    private BuildingService buildingService;

    @RequestMapping(value = "/admin/building/add", method = RequestMethod.POST, produces = "text/html")
    public ResponseEntity<String> addBuilding(@RequestBody BuildingDTO buildingDTO) {
        try{
            Building newBuilding = new Building(buildingDTO);
            return new ResponseEntity<String>(newBuilding.getName(), HttpStatus.OK);
        }catch (Exception ex) {
            return new ResponseEntity<String>("Data was not valid", HttpStatus.BAD_REQUEST);
        }
    }
}
_

My SecurityConfiguration.Java

_@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    public void configureAuthentication(
            AuthenticationManagerBuilder authenticationManagerBuilder)
            throws Exception {

        authenticationManagerBuilder
                .userDetailsService(this.userDetailsService).passwordEncoder(
                        passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public AuthenticationTokenFilter authenticationTokenFilterBean()
            throws Exception {
        AuthenticationTokenFilter authenticationTokenFilter = new AuthenticationTokenFilter();
        authenticationTokenFilter
                .setAuthenticationManager(authenticationManagerBean());
        return authenticationTokenFilter;
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
            .authorizeRequests()
                .antMatchers("/index.html", "/view/**", "/app/**", "/", "/api/login", "/api/register").permitAll()
                // defined Admin only API area 
                .antMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest()
                .authenticated()
                .and().csrf().disable();
                //if we use AngularJS on client side
//              .and().csrf().csrfTokenRepository(csrfTokenRepository()); 

        //add filter for adding CSRF token in the request 
        httpSecurity.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);

        // Custom JWT based authentication
        httpSecurity.addFilterBefore(authenticationTokenFilterBean(),
                UsernamePasswordAuthenticationFilter.class);
    }

    /**
     * If we use AngularJS as a client application, it will send CSRF token using 
     * name X-XSRF token. We have to tell Spring to expect this name instead of 
     * X-CSRF-TOKEN (which is default one)
     * @return
     */
    private CsrfTokenRepository csrfTokenRepository() {
          HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
          repository.setHeaderName("X-XSRF-TOKEN");
          return repository;
    }
  }
_

フロントエンドにAngularjsを使用していることに言及する必要がありますが、それでもログインでき、そのユーザーに対して正しい権限が表示されます。しかし、何らかの理由で、管理者としてログインしても、管理者ページにアクセスできません。

また、.hasAuthority("ROLE_ADMIN").hasRole("ROLE_ADMIN")(ROLE_のエラーを表示する)を試したので、.hasRole("ADMIN")に変更しましたが、まだ機能していません。

データベースには、adminのロールがROLE_ADMINとして保存されます。

6
P3P5

このようにしてみてください:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    private static String REALM="MY_TEST_REALM";

    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("bill").password("abc123").roles("ADMIN");
        auth.inMemoryAuthentication().withUser("tom").password("abc123").roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

      http.csrf().disable()
        .authorizeRequests()
        .antMatchers("/user/**").hasRole("ADMIN")
        .and().httpBasic().realmName(REALM).authenticationEntryPoint(getBasicAuthEntryPoint())
        .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);//We don't need sessions to be created.
    }

    @Bean
    public CustomBasicAuthenticationEntryPoint getBasicAuthEntryPoint(){
        return new CustomBasicAuthenticationEntryPoint();
    }

    /* To allow Pre-flight [OPTIONS] request from browser */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
    }
}

完全な構成の例: Secure Spring REST Basic Authentication using API

10
FuSsA
    import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();// We don't need sessions to be created.
    }

}

これは私のためにそれをしました。投稿リクエストを正常に送信できるようになりました

0
Ajay Menon