登录后 Spring Security 总是返回 403 accessDeniedPage [重复]

Posted

技术标签:

【中文标题】登录后 Spring Security 总是返回 403 accessDeniedPage [重复]【英文标题】:Spring Security always return the 403 accessDeniedPage after login [duplicate] 【发布时间】:2017-06-30 00:29:11 【问题描述】:

我是 Spring 新手,我一直在尝试使用 Spring Security 实现一个简单的登录页面。但它总是在提供登录凭据后访问被拒绝的 url。在我提供正确的用户名和密码后,loadUserByUsername() 方法总是返回一个用户。但我不知道如何找到返回该用户对象后发生的情况。

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

这是我的 spring 安全配置类

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");
        
    

在我提供正确的用户名和密码后,此方法总是返回一个用户。这就是它返回的内容

org.springframework.security.core.userdetails.User@a3b: 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 -->

【问题讨论】:

【参考方案1】:

Userme,您如何将角色名称构建到 Security 的 UserDetails 对象中?

请注意,通过 Spring Security 的 architectural decision,您必须在权限前添加“ROLE_”:

new SimpleGrantedAuthority("ROLE_" + roleName);

攻击

【讨论】:

这行得通。我也尝试使用 hasAuthority() 而不是 hasRole() 这样我就不必添加 ROLE 前缀

以上是关于登录后 Spring Security 总是返回 403 accessDeniedPage [重复]的主要内容,如果未能解决你的问题,请参考以下文章

登录 Spring Security 后如何返回基本令牌?

授权后返回上一页,Spring Security AuthenticationSuccessHundler

spring security使用自定义登录界面后,不能返回到之前的请求界面的问题

Spring Security 总是返回 HTTP 403 访问被拒绝 [关闭]

在 Spring Security 登录后,我被重定向到 CSS/JS 资源而不是 HTML 页面

spring security ajax登录