繁体   English   中英

我的 Spring Boot 项目中基于角色的授权

[英]Role based authorization in my Spring Boot project

这是我的 SuccessHandler 类

package com.myproject.configure;
    
import java.io.IOException;
import java.rmi.AccessException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

@Component
public class CustomLoginSuccessHandler implements AuthenticationSuccessHandler  {
    
//  @Override
//  protected void handle(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException  {
//      
//      String targetUrl = determineTargetUrl(authentication);
//      
//      System.out.println("Its a Target URL ---" + targetUrl);
//      if (response.isCommitted()) {
//          return;
//      }
//      RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
//      redirectStrategy.sendRedirect(request, response, targetUrl);
//  }
    
    protected String determineTargetUrl(Authentication authentication) {
        
        String url = "/login?error=true";

        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        List<String> roles = new ArrayList<String>();
        for (GrantedAuthority a : authorities) {
            roles.add(a.getAuthority());
        }
        
        if (roles.contains("SITE_ADMIN")) {
            System.out.println(roles.toString());
            url = "/admin/home";
        }
        else if (roles.contains("SITE_USERS")) {
            url = "/users/index";
            
        }
        
        return url;
        
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws IOException, ServletException {
        String redirectUrl = determineTargetUrl(authentication);
        
        if (redirectUrl == null) {
            throw new AccessException(redirectUrl);
        }
        new DefaultRedirectStrategy().sendRedirect(request, response, redirectUrl);
    }
}

这里我定义了两个不同的角色,一个是“ADMIN”,另一个是“USER”

我的用户有两个不同的实体类,角色有另一个。 对于不同的角色,我有两个不同的目的地。 但是当我运行我的应用程序并成功登录时,只有“USER”角色可以看到它的页面,而“ADMIN”角色用户看不到他们的页面。 但是我可以在控制台中看到 admin print 语句。 “这是管理员!!!!!”。 该怎么办 ? 或者我的错误在哪里?

这是我的实体类:

package com.myproject.entities;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "users")
public class Users {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id_users")
    private int idUsers;
    private String userName;
    private String password;
    
    @ManyToOne(cascade = CascadeType.ALL)
    private UserRole userRole;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "id_users")
    List<Recruitment> recruitments = new ArrayList<>();
    
    public Users() {
    }

    public Users(String userName, String password, UserRole userRole, List<Recruitment> recruitments) {
        this.userName = userName;
        this.password = password;
        this.userRole = userRole;
        this.recruitments = recruitments;
    }

    public int getIdUsers() {
        return idUsers;
    }

    public String getUserName() {
        return userName;
    }

    public String getPassword() {
        return password;
    }

    public UserRole getUserRole() {
        return userRole;
    }

    public List<Recruitment> getRecruitments() {
        return recruitments;
    }

    public void setIdUsers(int idUsers) {
        this.idUsers = idUsers;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setUserRole(UserRole userRole) {
        this.userRole = userRole;
    }

    public void setRecruitments(List<Recruitment> recruitments) {
        this.recruitments = recruitments;
    }

    @Override
    public String toString() {
        return "Users [idUsers=" + idUsers + ", userName=" + userName + ", password=" + password + ", userRole="
                + userRole + ", recruitments=" + recruitments + "]";
    }

    
    
    
}
package com.myproject.entities;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "user_role")
public class UserRole {

    @Id
    @Column(name = "iduser_role")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int idUserRole;
    private String roleName;
    
    @OneToMany(mappedBy = "userRole")
    private List<Users> users;

    public UserRole() {
    }

    public int getIdUserRole() {
        return idUserRole;
    }

    public String getRoleName() {
        return roleName;
    }

    public List<Users> getUsers() {
        return users;
    }

    public void setIdUserRole(int idUserRole) {
        this.idUserRole = idUserRole;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }

    public void setUsers(List<Users> users) {
        this.users = users;
    }

}

这是我的控制器:

@RequestMapping("/login")
    public String login() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        
        if (authentication == null || authentication instanceof AnonymousAuthenticationToken) {
            return "login";
        }
        
        return "redirect:/login";
        
    }
    
    @RequestMapping("/logout")
    public String logout() {
        
        return "login";
        
    }
    
    @GetMapping
    public String login(@RequestParam(value = "error", defaultValue = "false") boolean loginError) {
        if (loginError) {
            return "error-404";
            }
        return "login";
        
    }
    
    @RequestMapping("/admin/home")
public String loginAdmin(Model model) {
    
    System.out.println("From Admin Controller");
    return "/admin/home";
}

@RequestMapping("/user/home")
public String loginUser(Model model) {
    
    System.out.println("From User Controller");
    
    return "/user/home";
}

这是我的 WebSecurityConfiguration 文件:

package com.myproject.configure;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import com.recruitmentmanagement.service.CustomUserDetailsService;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomUserDetailsService userDetailsService;
    
    @Autowired
    private CustomLoginSuccessHandler successHandler;
    
    
    
    @Bean
    public PasswordEncoder  passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {

        httpSecurity
        .authorizeRequests()
        .antMatchers("/login","/registration", "/process_registration", "/userhome", "/landing", "/order", "/jobdetails/**").permitAll()
        .antMatchers("/user/**").hasAnyAuthority("USER", "ADMIN")
        .antMatchers("/admin/**").hasAnyAuthority("ADMIN")
        .anyRequest().authenticated()
        .and()
        .csrf().disable().formLogin()
        .loginPage("/login")
        .failureUrl("/login?error=true")
        .successHandler(successHandler)
        .usernameParameter("userName")
        .passwordParameter("password")
    .and()
    .logout()
    .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
    .logoutSuccessUrl("/login").and()
    .exceptionHandling()
    .accessDeniedPage("/access-denied");
        
    }
    
    @Bean
    public LogoutSuccessHandler logoutSuccessHandler() {
        return new CustomLogoutSuccessHandler();
    }

    @Override
    public void configure(WebSecurity webSecurity) throws Exception {
        webSecurity.ignoring().antMatchers("/webjars/**",
                                            "/css/**", 
                                            "/js/**",
                                            "/images/**",
                                            "/node_modules/**",
                                            "/bower_components/**");
    }

    
    @Bean
    public DaoAuthenticationProvider authProvider() throws Exception {
        
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setPasswordEncoder(passwordEncoder());
        authenticationProvider.setUserDetailsService(userDetailsService);
        return authenticationProvider;
    }
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        System.out.println("WebSecurityConfig -- " + authProvider().toString());
        auth.authenticationProvider(authProvider());
    }
    
}

考虑使用官方 Spring Security 模型

所以一切都会为你做的

您可以为某些页面指定角色和权限

好的,首先,您必须扩展 AuthenticationSuccessHandler,并且您的句柄方法应如下所示

@Component
public class CustomSuccessHandler implements AuthenticationSuccessHandler {

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

        String redirectUrl = determineTargetUrl(authentication);

        if (redirectUrl == null) {
            throw new SomeException();
        }

        new DefaultRedirectStrategy().sendRedirect(request, response, redirectUrl);
    }
}

此时 url 'login?error=true' 是多余的。 您可以安全地从 defineTargeUrl 中删除它,因为您是在 WebSecurityConfig 类中的失败登录 url 中定义的。

有了这个说控制器应该看起来像这样

@Controller
@RequestMapping
public class TestController {

    ...
}

我看不到您的控制器类的顶部,因此请确保您已获得这两个注释。 定义以下条件时也要小心

hasAnyAuthority("USER", "ADMIN")

roleName.contains("ADMIN")

您必须在重定向类中使用“equals”,这可能会导致歧义

实际上,我只获得了 [USER] 作为权限,这是我在打印 authentication.getAuthorities() 时发现的; 来自我的 SuccessHandler 课程。 当我从 WebSecurity 类检查我的 authProvider() 函数时,我的用户权限由我的 CustomUserDetailsS​​ervice 提供。 我检查了我的 CustomUserDetailsS​​ervice 类,发现以下内容:

package com.myproject.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
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 com.recruitmentmanagement.entities.Users;

@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    UsersService usersService;
    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        
        final Users users = usersService.getUsersByUsers(username);
        
        if (users == null) {

            throw new UsernameNotFoundException("User not found !!!");              
        }

        UserDetails userDetails = User.withUsername(users.getUserName()).password(users.getPassword()).authorities("USER").build(); 
        
        
        
        return userDetails;

    }

}

然后我更改我的代码,这是我的最终 CustomUserDetailService 类

package com.myproject.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
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 com.recruitmentmanagement.entities.Users;

@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    UsersService usersService;
    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        
        final Users users = usersService.getUsersByUsers(username);
        
        if (users == null) {

            throw new UsernameNotFoundException("User not found !!!");              
        }

        UserDetails userDetails = User.withUsername(users.getUserName()).password(users.getPassword()).authorities(users.getUserRole().getRoleName()).build();  
        
        
        
        return userDetails;

    }

}

感谢所有试图帮助我的人。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM