2017-02-11 327 views
0

我是Spring的新手,我一直试图使用spring security来实现一个简单的登录页面。但它总是会在提供登录凭证后访问拒绝URL。在我提供正确的用户名和密码后,loadUserByUsername()方法总是返回一个用户。但是我不知道如何找到那个用户对象返回后会发生什么。Spring Security在登录后总是返回403 accessDeniedPage

用户只有一个角色。该方法返回用户SUPER_USER角色。

这里是我的春天的安全配置类

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.ComponentScan; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.security.authentication.AuthenticationTrustResolver; 
import org.springframework.security.authentication.AuthenticationTrustResolverImpl; 
import org.springframework.security.authentication.dao.DaoAuthenticationProvider; 
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.configuration.EnableWebSecurity; 
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 
import org.springframework.security.core.userdetails.UserDetailsService; 
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 
import org.springframework.security.crypto.password.PasswordEncoder; 

@Configuration 
@EnableWebSecurity 
@ComponentScan(basePackageClasses = AppConfig.class) 
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 

    @Autowired 
    UserDetailsService userDetailsService; 

    @Autowired 
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception { 

     System.out.println("Inside configureGlobalSecurity method"); 

     auth.userDetailsService(userDetailsService); 
     auth.authenticationProvider(authenticationProvider()); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     System.out.println("Inside configure method"); 
     http.authorizeRequests().antMatchers("/", "/list") 
       .access("hasRole('SUPER_USER') or hasRole('NORMAL_USER') or hasRole('CUSTOMER')") 
       .and().formLogin().loginPage("/login") 
       .loginProcessingUrl("/login").usernameParameter("username").passwordParameter("password").and() 
       .csrf().and().exceptionHandling().accessDeniedPage("/Access_Denied"); 
    } 

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

    @Bean 
    public DaoAuthenticationProvider authenticationProvider() { 
     System.out.println("Inside authenticationProvider method"); 
     DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); 
     authenticationProvider.setUserDetailsService(userDetailsService); 
     authenticationProvider.setPasswordEncoder(passwordEncoder()); 
     return authenticationProvider; 
    } 


    @Bean 
    public AuthenticationTrustResolver getAuthenticationTrustResolver() { 
     return new AuthenticationTrustResolverImpl(); 
    } 
} 

这是我UserDetailsS​​erviceImpl类

import java.util.HashSet; 
import java.util.Set; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.security.core.GrantedAuthority; 
import org.springframework.security.core.authority.SimpleGrantedAuthority; 
import org.springframework.security.core.userdetails.UserDetails; 
import org.springframework.security.core.userdetails.UserDetailsService; 
import org.springframework.security.core.userdetails.UsernameNotFoundException; 
import org.springframework.stereotype.Service; 
import org.springframework.transaction.annotation.Transactional; 

import com.dao.user.UserDao; 
import com.entity.user.User; 

@Service("userDetailsService") 
@Transactional 
public class UserDetailsServiceImpl implements UserDetailsService { 

    @Autowired 
    UserDao userDao = null; 

    @Override 
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 
     User user = userDao.getUserByUsername(username); 
     if(user!=null) { 
      Set<GrantedAuthority> grantedAuthorities = new HashSet<>(); 
      grantedAuthorities.add(new SimpleGrantedAuthority(user.getRole().getDescription().getStringVal())); 
      org.springframework.security.core.userdetails.User u = new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), true, true, true, true,grantedAuthorities); 
      return u; 
     } else { 
      throw new UsernameNotFoundException("User Does not Exist"); 
     } 
    } 
} 

此方法始终返回一个用户后,我提供正确的用户名和password.This是它返回

[email protected]: Username: RM; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: SUPER_USER 

这是控制器类

import org.springframework.security.authentication.AuthenticationTrustResolver; 
import org.springframework.security.core.Authentication; 
import org.springframework.security.core.context.SecurityContextHolder; 
import org.springframework.stereotype.Controller; 
import org.springframework.ui.ModelMap; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.bind.annotation.ResponseBody; 


@Controller 
@RequestMapping("/") 
public class LoginController { 


@Autowired 
AuthenticationTrustResolver authenticationTrustResolver; 


@RequestMapping(value = { "/", "/list" }, method = RequestMethod.GET) 
public String listUsers(ModelMap model) { 

    System.out.println("Inside controller list"); 

    return "first"; 
} 



@RequestMapping(value = "/Access_Denied", method = RequestMethod.GET) 
@ResponseBody 
public String accessDeniedPage(ModelMap model) { 

    return "Access Dennied"; 
} 

@RequestMapping(value = "/login", method = RequestMethod.GET) 
public String loginPage() { 
    System.out.println("Inside controller login"); 
    if (isCurrentAuthenticationAnonymous()) { 
     return "login"; 
    } else { 
     return "redirect:/list"; 
    } 
} 


@RequestMapping(value="/logout", method = RequestMethod.GET) 
public String logoutPage (HttpServletRequest request, HttpServletResponse response){ 
    Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 
    if (auth != null){  

     SecurityContextHolder.getContext().setAuthentication(null); 
    } 
    return "redirect:/login?logout"; 
} 


/** 
* This method returns true if users is already authenticated [logged-in], else false. 
*/ 
private boolean isCurrentAuthenticationAnonymous() { 
    final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 
    return authenticationTrustResolver.isAnonymous(authentication); 
} 

这是我的登录表单

<form id="login" name="login" class="form-signin" action="/SpringView/login" method=POST> 
    <span id="reauth-email" class="reauth-email"></span> 
    <input type="text" id="username" name="username" class="form-control" placeholder="Email address" required 
      autofocus> 
    <input type="password" id="password" name="password" class="form-control" placeholder="Password" required> 
    <div id="remember" class="checkbox"> 
     <label> 
      <input type="checkbox" value="remember-me"> Remember me 
     </label> 
    </div> 
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> 
    <button class="btn btn-lg btn-block btn-signin " type="submit">Sign in</button> 
</form><!-- /form --> 

回答

4

Userme,你是如何构建的角色名,以安全的UserDetails对象呢?

请注意,由Spring Security的architectural decision你必须在前面加上 'ROLE_' 给你权威:

new SimpleGrantedAuthority("ROLE_" + roleName); 

ATT

+0

这个工作。我也尝试使用hasAuthority()而不是hasRole(),这样我就不必添加ROLE前缀 – userme