当前位置: 首页 > 知识库问答 >
问题:

Spring Boot Security 403"拒绝访问"

乔宏峻
2023-03-14

我正在制作一个RESTFul API(不是web应用程序)并添加Spring Security性,但无法成功完成。

在阅读了大量有关stackoverflow的文章和帖子后,我终于发布了我的问题。请检查一下,让我知道我遗漏了什么或配置错误了什么?

基本实体

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
abstract class BaseEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "ID", nullable = false, updatable = false)
    private Long ID;

    @CreatedBy
    @Column(name = "CreatedBy", nullable = false, updatable = false)
    private String createdBy;

    @CreatedDate
    @Column(name = "CreatedDate", nullable = false, updatable = false)
    private LocalDateTime createdDate;

    @LastModifiedBy
    @Column(name = "ModifiedBy")
    private String modifiedBy;

    @LastModifiedDate
    @Column(name = "ModifiedDate")
    private LocalDateTime modifiedDate;

    ...getters setters
}

角色实体

@Entity
@Table(name = "ROLE")
public class Role extends BaseEntity {

    @Column(name = "Name")
    private String name;

    ...getters setters
}

用户实体

@Entity
@Table(name = "USER")
public class User extends BaseEntity {

    @Column(name = "EmiratesID", unique = true, nullable = false, updatable = false)
    private String emiratesID;

    @Column(name = "FirstName")
    private String firstName;

    @Column(name = "LastName")
    private String lastName;

    @Column(name = "StaffID", unique = true, nullable = false, updatable = false)
    private String staffID;

    @Column(name = "Email", unique = true, nullable = false)
    private String email;

    @Column(name = "Password", nullable = false)
    private String password;

    @ManyToOne(optional = false, cascade = CascadeType.MERGE)
    @JoinColumn(name = "ROLE_ID")
    private Role role;

    ...getters setters

    public UserDetails currentUserDetails() {
        return CurrentUserDetails.create(this);
    }

}

SecurtiyConfig类

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    private final DataSource dataSource;
    private final UserDetailsServiceImplementation userDetailsService;

    @Autowired
    public SecurityConfig(final DataSource dataSource, final UserDetailsServiceImplementation userDetailsService) {
        this.dataSource = dataSource;
        this.userDetailsService = userDetailsService;

    }

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

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.authorizeRequests()
                .antMatchers("/console/**").permitAll()
                .antMatchers("/", "/greetUser", "/register", "/login").permitAll()
                .antMatchers("/user/**").hasAnyAuthority(ROLES.USER.getValue(), ROLES.ADMIN.getValue())
                .antMatchers("/admin/**").hasAuthority(ROLES.ADMIN.getValue()).anyRequest().authenticated();
        httpSecurity.csrf().disable();

        // required to make H2 console work with Spring Security
        httpSecurity.headers().frameOptions().disable();

    }

    @Autowired
    public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());

    }

    @Override
    public void configure(WebSecurity webSecurity) {

        webSecurity.ignoring().antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**");
    }

CurrentUserDetails

public class CurrentUserDetails implements UserDetails {

    private String ROLE_PREFIX = "ROLE_";

    private Long userID;
    private String emiratesID;
    private String firstName;
    private String lastName;
    private String staffID;
    private String email;
    private String password;
    private Role role;

    public CurrentUserDetails(Long ID, String emiratesID, String firstName,
                              String lastName, String staffID, String email,
                              String password, Role role) {

        super();
        this.userID = ID;
        this.emiratesID = emiratesID;
        this.firstName = firstName;
        this.lastName = lastName;
        this.staffID = staffID;
        this.email = email;
        this.password = password;
        this.role = role;

    }

    public Long getUserID() {
        return userID;
    }

    public String getEmiratesID() {
        return emiratesID;
    }

    public String getEmail() {
        return this.email;
    }

    public Role getRole() {
        return this.role;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> grantedAuthority = new ArrayList<>();

        grantedAuthority.add(new SimpleGrantedAuthority(ROLE_PREFIX + role.getName()));

        return grantedAuthority;
    }

    @Override
    public String getPassword() {
        return this.password;
    }

    @Override
    public String getUsername() {
        return this.email;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    /**
     * Helper method to add all details of Current User into Security User Object
     * @param user User
     * @return UserDetails
     */
    public static UserDetails create(User user) {
        return new CurrentUserDetails(user.getID(), user.getEmiratesID(),
                                      user.getFirstName(), user.getLastName(),
                                      user.getStaffID(), user.getEmail(),
                                      user.getPassword(), user.getRole());
    }

}

UserDetailsService

@Component/@Service
public class UserDetailsServiceImplementation implements UserDetailsService {

    private static final Logger userDetailsServiceImplementationLogger = LogManager.getLogger(UserDetailsServiceImplementation.class);
    private final UserRepository userRepository;

    @Autowired
    public UserDetailsServiceImplementation(final UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if (StringUtils.isEmpty(username)) {
            userDetailsServiceImplementationLogger.error("UserDetailsServiceImplementation.loadUserByUsername() :: FAILED");

            throw new UsernameNotFoundException("UserName is not passed");
        }

        User userFound = userRepository.findByEmail(username);

        if (userFound == null) {
            userDetailsServiceImplementationLogger.error("No user found with given username = {}", username);

            throw new UsernameNotFoundException("No user found with given username");
        }

        return userFound.currentUserDetails();
    }

}

用户控制器类

@RestController
@RequestMapping(value = "/user")
public class UserController {

    private static Logger userControllerLogger = LogManager.getLogger(UserController.class);

    @Autowired
    private PropertiesConfig propertiesConfig;

    @Autowired
    private UserManager userManager;

    @RequestMapping(value = "/listAll", method = RequestMethod.GET)
    public ResponseEntity<Map<String, Object>> getUsersList() {
        userControllerLogger.info("UserController.getUsersList()[/listAll] :: method call ---- STARTS");

        LinkedHashMap<String, Object> result = userManager.findAllUsers();

        userControllerLogger.info("UserController.getUsersList()[/listAll] :: method call ---- ENDS");

        return new ResponseEntity<>(result, HttpStatus.OK);
    }

}

管理员控制类

@RestController
@RequestMapping(value = "/admin")
public class AdminController {

    private static final Logger adminControllerLogger = LogManager.getLogger(AdminController.class);

    private final PropertiesConfig propertiesConfig;
    private final UserManager userManager;

    @Autowired
    public AdminController(final PropertiesConfig propertiesConfig, final UserManager userManager) {
        this.propertiesConfig = propertiesConfig;
        this.userManager = userManager;

    }

    @RequestMapping(value = "/home", method = {RequestMethod.GET})
    public ResponseEntity<String> adminPortal(@RequestBody String adminName) {
        adminControllerLogger.info("AdminController.adminPortal()[/home] :: method call ---- STARTS");

        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        UserDTO adminUser = userManager.findUserByEmail(auth.getName());

        if (adminUser == null) {
            throw new UsernameNotFoundException(propertiesConfig.getProperty(ApplicationProperties.Messages.NO_USER_FOUND.getValue()));
        }

        adminControllerLogger.info("AdminController.adminPortal()[/home] :: method call ---- ENDS");

        return new ResponseEntity<>(ApplicationConstants.GeneralConstants.WELCOME.getValue() + adminUser.getStaffID(), HttpStatus.OK);

    }

}

数据sql

尝试使用角色\用户/管理员和用户/管理员这两个值

INSERT INTO ROLE(ID, CreatedBy, CreatedDate, ModifiedBy, ModifiedDate, Name) VALUES (-100, 'Muhammad Faisal Hyder', now(), '', null, 'ROLE_ADMIN'/'ADMIN')
INSERT INTO ROLE(ID, CreatedBy, CreatedDate, ModifiedBy, ModifiedDate, Name) VALUES (-101, 'Muhammad Faisal Hyder', now(), '', null, 'ROLE_USER'/'USER')

INSERT INTO USER(ID, CreatedBy, CreatedDate, ModifiedBy, ModifiedDate, EmiratesID, FirstName, LastName, Email, StaffID, Password, ROLE_ID) VALUES (-1, 'Muhammad Faisal Hyder', now(), '', null, 'ABCDEF12345', 'Muhammad Faisal', 'Hyder', 'faisal.hyder@gmail.com', 'S776781', '$2a$10$qr.SAgYewyCOh6gFGutaWOQcCYMFqSSpbVZo.oqsc428xpwoliu7C', -100)
INSERT INTO USER(ID, CreatedBy, CreatedDate, ModifiedBy, ModifiedDate, EmiratesID, FirstName, LastName, Email, StaffID, Password, ROLE_ID) VALUES (-2, 'Muhammad Faisal Hyder', now(), '', null, 'BCDEFG12345', 'John', 'Smith', 'John.Smith@gmail.com', 'S776741', '$2a$10$j9IjidIgwDfNGjNi8UhxAeLuoO8qgr/UH9W9.LmWJd/ohynhI7UJO', -101)

我已经附上了我认为必要的所有可能的课程。请让我知道可能的问题。

我读过的文章;SO-1,SO-2,SO-3,SO-4,第1条,第2条

已解决

@dur感谢你指出这一点,也感谢其他人的有益见解。

1- Use ROLE_ in db entries.
2- Once prefix is added in db then no need to explicitly add this in
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities(){...}
3- .and().httpBasic(); was missing from SpringSecurity configuration.
4- This is very detailed, might be helpful to others as well.

共有2个答案

路欣荣
2023-03-14

正如@dur在评论中指出的,我正在为我的问题添加答案。

1- Use ROLE_ in db entries.
2- Once prefix is added in db then no need to explicitly add this in
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities(){...}
3- .and().httpBasic(); was missing from SpringSecurity configuration.

因为这篇文章非常详细,可能对其他人也有帮助。有关正确答案,请参阅我的git回购

长孙阳成
2023-03-14

我看到的问题是,您正在授予权限ADMIN的访问权限,但您没有将此权限添加到货币用户详细信息,您只是添加了他们的角色。您也应该添加权限,即。

@Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> grantedAuthority = new ArrayList<>();

        grantedAuthority.add(new SimpleGrantedAuthority(ROLE_PREFIX + role.getName()));

        // add authority in addition to role (no role prefix)
        grantedAuthority.add(new SimpleGrantedAuthority(role.getName()));

        return grantedAuthority;
    }
 类似资料:
  • 当我创建新用户或授予现有特权,我得到了这个错误: 授予所有表上的权限ok(信息\u架构除外),在此表上我得到了拒绝访问错误。我怎么能修理?转储所有数据库,删除所有数据库,然后从转储还原?

  • 为什么当我试图创建InputStream时,下面的代码会给我一个File Not Found异常?我的inputdirectory定义为一个文件,其值为“D:\general\images\small_images”(不带引号),我的用户对该文件具有完全的写权限。我正在使用Windows7,并以管理员的身份运行eclipse IDE。 如有任何帮助,不胜感激。

  • 我找到了商店定位器的谷歌教程:https://developers.google.com/maps/articles/phpsqlsearch_v3#findnearsql MySQL表完成了,它在我的服务器上工作。我可以在phpmyadmin中正确地写入地址和执行操作 但是在“用PHP输出XML”的教程中,我不能继续了。 我已经创建了文件phpsqlsearch_dbinfo.php,把我的数据

  • 问题内容: 我有以下代码: 当我尝试保存文件时,出现以下错误 原因可能是什么,我该如何解决?我确实对此文件夹具有读写权限。 问题答案: 当创建一个new时,应该提供文件名,而不仅是要放置文件的目录。 尝试类似的东西

  • 问题内容: 这是我的编辑从第27行到第39行的代码: 我认为我的问题可能与Win7教授有关:(访问被拒绝) 如何解决这个问题,或者我需要做些什么或阅读才能使它起作用? 谢谢你不燃烧。 我只是更改了文件夹选项,使我获得完整的(Access …),现在我只需要弄清楚为什么在运行javac VendingMachine.java时为什么没有得到任何输出,我想是有一个新问题。 问题答案: 您的工作目录为。

  • 问题内容: 这是我的Java代码: 一个非常简单的任务,我尝试使用AmazonS3 Java客户端访问S3,但是此行不断失败,并给了我以下异常: 一个非常明显的错误代码:403,它表示我的AWS凭证是错误的,但是,这与我的同事用来访问同一s3存储桶的凭证完全相同,以排除我在某处出现错字的可能性,因此我确实删除了我以前的一个,并使用了我同事发送给我的那个,并将其放在〜/ .aws /下 我还研究了其

  • 问题内容: 我正在尝试读取文件夹中的文件,但是当我运行该程序时,它将引发此异常。我也尝试了其他一些文件夹。它引发相同的异常。 问题答案: 您无法打开和读取目​​录,无法使用和方法区分文件和文件夹。您可以使用和方法获取文件夹的内容(分别用于文件名和s),还可以指定一个过滤器来选择列出的文件的子集。

  • 我正在使用wamp服务器,我的phpMyAdmin页面返回了以下错误。 Wamp服务器版本:2.2 MySQL版本:5.5.24 #1045-用户“root”@“本地主机”的访问被拒绝(使用密码:是) 我编辑了我的配置文件wamp\app\phpmyadmin4.1.14\config.inc.php: 但这并没有解决问题。任何帮助都将不胜感激。