根据具有 jdbc 身份验证的角色重定向到控制器中的 url

Redirect to url in controller based on role with jdbc authentication

我正在学习 Spring 安全。我已经基于 github 框架项目制作了一个标准的登录和注册页面。只要我在数据库中只使用一个角色,我就可以轻松地通过我得到的一个角色来管理默认成功 url。但是现在我想添加两个基于 ADMIN 和 USER 角色的默认 url。 我在这里阅读了这个 determine target url based on roles in spring security 3.1 答案,并尝试实现它,但 isUserInRole() 方法总是 return 一个错误值。我正在使用 jdbc 身份验证。

我的 MVC 配置:

@Configuration
@ComponentScan(basePackages={"hu.kreszapp"})
public class MvcConfig extends WebMvcConfigurerAdapter{

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

}

我的安全配置:

@Configuration
@EnableWebSecurity
@ComponentScan(basePackages={"hu.kreszapp"})
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private DataSource dataSource;

    @Value("${spring.queries.users-query}")
    private String usersQuery;

    @Value("${spring.queries.roles-query}")
    private String rolesQuery;


    @Override
    protected void configure(AuthenticationManagerBuilder auth)
            throws Exception {
        auth.
                jdbcAuthentication()
                .usersByUsernameQuery(usersQuery)
                .authoritiesByUsernameQuery(rolesQuery)
                .dataSource(dataSource)
                .passwordEncoder(bCryptPasswordEncoder);
    }

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

        http.
                sessionManagement() //session management
                .sessionCreationPolicy(SessionCreationPolicy.ALWAYS) //session management
                .and()
                .authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/login").permitAll()
                .antMatchers("/registration").permitAll()
                .antMatchers("/home").hasRole("ADMIN")//hasAuthority("ADMIN")
                .antMatchers("/game").hasRole("USER").anyRequest()//hasAuthority("USER").anyRequest()
                .authenticated().and().csrf().disable().formLogin()
                .loginPage("/login").failureUrl("/login?error=true")
                .defaultSuccessUrl("/default")
                .usernameParameter("email")
                .passwordParameter("password")
                .and().logout()
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                .logoutSuccessUrl("/").and().exceptionHandling()
                .accessDeniedPage("/access-denied");
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web
                .ignoring()
                .antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/templates/images/**");
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");

        auth
                .inMemoryAuthentication()
                .withUser("admin").password("admin").roles("ADMIN");

    }
}

我的控制器:

 @RequestMapping(value="/home", method = RequestMethod.GET)
    public ModelAndView home(){
        ModelAndView modelAndView = new ModelAndView();
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        User user = userService.findUserByEmail(auth.getName());
        modelAndView.addObject("userName", "Welcome " + user.getUsername() +  " (" + user.getEmail() + ")");
        modelAndView.addObject("adminMessage","Content Available Only for Users with Admin Role");
        modelAndView.setViewName("/home");

        return modelAndView;
    }

    @RequestMapping(value="/game", method = RequestMethod.GET)
    public ModelAndView game(){
        ModelAndView modelAndView = new ModelAndView();
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        User user = userService.findUserByEmail(auth.getName());
        modelAndView.addObject("userName", "Welcome " + user.getUsername() +  " (" + user.getEmail() + ")");
        modelAndView.addObject("adminMessage","Content Available Only for Users with Admin Role");
        modelAndView.setViewName("/game");

        return modelAndView;
    }

    @RequestMapping(value="/default")
    public String default(HttpServletRequest request){
        Principal u = request.getUserPrincipal();
        logger.info("user principal:" + u.toString());

        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        String role = auth.getAuthorities().toString();
        logger.info("Role:" + u.toString());


        boolean r1 = request.isUserInRole("USER");
        boolean r2 = request.isUserInRole("ADMIN");
        boolean r3 =request.isUserInRole("1");
        boolean r4 =request.isUserInRole("2");

        logger.info("isUserInRole values:"+ r1 + " " + r2 + " " + r3 +" "+ r4);



        if(request.isUserInRole("ADMIN")) {
            logger.info("Admin check lefut!");
            return "home";
        }
        logger.warn("Admin check nem fut let!");

        return "game";
    }

在我的默认控制器中 - 它代表按角色重定向到指定页面 - request.isUserInRole("ADMIN") 方法总是 returns 具有错误值......但是我有 ADMIN 用户我的数据库中的角色和日志也证明我指定的用户已被授予管理员角色:

Principal u = request.getUserPrincipal();
    logger.info("user principal:" + u.toString());

    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    String role = auth.getAuthorities().toString();
    logger.info("Role:" + u.toString());

我的问题是,为什么这种方法不能通知 ADMIN 用户,我如何才能通过 jdbc 身份验证按角色重定向?

提前致谢

Spring 安全性为角色添加 ROLE_ 前缀。代码 request.isUserInRole("USER") 将查找 ROLE_USER。如果您在数据库中的角色也没有前缀,它们将不相等。

您还可以在 configure(HttpSecurity http) 方法中设置 Spring 安全使用的前缀。

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .servletApi().rolePrefix("MY_ROLE_PREFIX_");
}

http://docs.spring.io/spring-security/site/docs/current/apidocs/org/springframework/security/config/annotation/web/builders/HttpSecurity.html