Spring安全角色访问,登录

时间:2017-07-18 14:26:29

标签: spring spring-mvc spring-security spring-data-jpa

我遇到了一些实现spring安全性的问题,特别是USER和ADMIN。我希望每种角色类型都重定向到其各自的页面/用户和/ admin。我已经阅读了无数的教程,每个教程似乎与最后一个教程有点不同,这一切都非常令人困惑。我想知道是否有人可以定义我需要做什么,因为我不认为我对目前为止所做的事情太过分了。目前的问题是它没有按照说法重定向,我不认为它正在创建一个会话,因为当我尝试在登录后检索任何Prinicipal.getName()时它始终为null。除此之外我还有什么我想念的吗?非常感谢任何帮助。

几乎整个应用程序都禁止注册功能,userRepo和views。

公共类UserDetailService实现UserDetailsS​​ervice {

@Autowired
UserRepo userRepo;

public UserDetailService(UserRepo userRepo){
    this.userRepo=userRepo;
}

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

    //Find a user by username
    User user = this.userRepo.findByUsername(username);

    //Check if it's null
    if(user == null) throw new UsernameNotFoundException(username);
    //if not then return user detail with arguments
    else return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), getAuthorities(user));
}

@SuppressWarnings("serial")
public static Collection<GrantedAuthority> getAuthorities(User user) {
    // make everyone ROLE_USER
    Collection<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
    GrantedAuthority grantedAuthority = new GrantedAuthority() {

        @Override
        public String getAuthority() {
            if (user.getRole().equals("ROLE_USER")) return "ROLE_USER"; 
            else return "ROLE_ADMIN";
        }
    };
    grantedAuthorities.add(grantedAuthority);

    grantedAuthority = new GrantedAuthority() {

        @Override
        public String getAuthority() {
            return "ROLE_USER";
        }
    };
    grantedAuthorities.add(grantedAuthority);
    return grantedAuthorities;
}

@服务 公共类UserServices {

@Autowired
private UserRepo userRepo;

//User register service
public void register(User user) {       
    //Encrypt password
    user.setPassword(BCrypt.hashpw(user.getPassword(), BCrypt.gensalt()));
    user.setRole("ROLE_USER");
    this.userRepo.save(user);               
}

//Used to add admin accounts on boot
public void adminOnBoot(User user) {
    user.setPassword(BCrypt.hashpw(user.getPassword(), BCrypt.gensalt()));
    this.userRepo.save(user);
}

//Return the list of users available
public List<User> getAllUsers() {
    return this.userRepo.findAll();     
}

//Check if user exists by a username
public Boolean existsByUsername(String username) {
    return this.userRepo.existsByUsername(username);
}

//Check if user exists by an email
public Boolean existsByEmail(String emailAddress) {
    return this.userRepo.existsByEmail(emailAddress);
}

//Login user by the login forms username and password
public User loginUserByForm(LoginForm loginForm) {      
    User user = this.userRepo.findByUsername(loginForm.getUsername());      
    if(user != null && BCrypt.checkpw(loginForm.getPassword(), user.getPassword()))
        return user;

    else return null;
}

@Controller 公共类LoginController {

@Autowired
private UserServices userService;

//LOGIN PROCESS - NO NEED FOR SEPERATE VIEW
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String verifyLogin(@Valid @ModelAttribute("loginForm") LoginForm loginForm, Model model, HttpServletRequest request) {

    User user = userService.loginUserByForm(loginForm);
    if(user == null) {

        //Add a model attribute for an error
        model.addAttribute("loginError", "notNull");

        //Passing the no. of registered users
        model.addAttribute("users", userService.getAllUsers()); 
        model.addAttribute("userCount", userService.getAllUsers().size()); 

        return "index";
    }

    //create the HttpSession
    request.getSession().setAttribute("user", user);

    //Passing the no. of registered users
    model.addAttribute("users", userService.getAllUsers()); 
    model.addAttribute("userCount", userService.getAllUsers().size()); 
    model.addAttribute("username", user.getUsername()); 

    //TO DO
    return "admin";     
}

@RequestMapping("/logout")
public String verifyLogout(HttpServletRequest request, HttpServletResponse response) {

    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    if (auth != null){    
        new SecurityContextLogoutHandler().logout(request, response, auth);
    }
    return "redirect:/login?logout";

}

}

@Configuration @EnableWebSecurity 公共类SpringSecurityConfigurer扩展了WebSecurityConfigurerAdapter {

@Autowired 
private UserRepo userRepo;
@Autowired
private CustomAuthenticationHandler authHandler;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsServiceBean());
}

@Override
public UserDetailsService userDetailsServiceBean() throws Exception {
    return new UserDetailService(userRepo);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
             //CSS FILES AND IMAGES
            .antMatchers("/css/**", "/img/**", "/js/**").permitAll()
             //PAGES FOR ALL PEOPLE
            .antMatchers("/", "/login", "/register/**").permitAll()
             //PAGES FOR ADMIN
            .antMatchers("/admin/**").hasAuthority("ADMIN")
             //PAGES FOR USERS
            .antMatchers("/user/**").hasAuthority("USER")
            .anyRequest().authenticated()
        .and()
        .formLogin()
        .loginProcessingUrl("/login")
        .loginPage("/")
        .failureUrl("/?error")
        .and()
        .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/");
    ;
}

}

公共类CustomAuthenticationHandler实现AuthenticationSuccessHandler {

@Autowired
UserRepo userRepo;

@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                    Authentication authentication) throws ServletException, IOException {

    HttpSession session = request.getSession();
    User user = userRepo.findByUsername(authentication.getName());

    session.setAttribute("user", user);
    response.setStatus(HttpServletResponse.SC_OK);
    if (user.getRole().equals("ROLE_ADMIN")) {
        response.sendRedirect("/admin/");
    } else {
        response.sendRedirect("/user/" + user.getUsername());
    }
}

}

2 个答案:

答案 0 :(得分:0)

问题在于您的角色定义:

WebSecurityConfiration

您正在唱歌 ADMIN

.antMatchers("/admin/**").hasAuthority("ADMIN")

但您正在寻找ROLE_ADMIN重定向到/ admin

user.getRole().equals("ROLE_ADMIN")

与USER相同,您正在寻找 USER ,但您已定义 ROLE_USER

此致

答案 1 :(得分:-1)

经过几个小时,我终于成功了。对于任何有类似自定义登录表单问题的人(不是j_spring_security_check ..)我设置了一个新的 CustomAuthenticationProvider.java

@Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        User user = userRepo.findByUsername(authentication.getName());

        String name = authentication.getName();
        String password = authentication.getCredentials().toString();

        if(user != null) return new UsernamePasswordAuthenticationToken(name, password, getAuthorities(user));
        return null;
    }

我认为将其添加到安全配置中如下...

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(cap);
}

简单的解决方法确实令人困惑,因为有太多不同的信息。 问候, 本