春季引导安全性 JDBC 基本身份验证失败

huangapple 未分类评论47阅读模式
英文:

Spring Boot Security JDBC Basic Authentication Failure

问题

我正在使用Spring Boot Security应用程序设置JDBC身份验证与PostgreSQL数据库连接。

我已经为用户和角色创建了以下表,分别命名为'users'和'user_authorities'。

CREATE SEQUENCE users_id_seq
  INCREMENT 1
  START 1
  MINVALUE 1
  MAXVALUE 2147483647
  CACHE 1;

CREATE TABLE users (
  id       integer NOT NULL DEFAULT nextval('users_id_seq'),
  username VARCHAR ( 100 ) UNIQUE NOT NULL,
  password VARCHAR ( 100 ) NOT NULL,
  enabled  boolean NOT NULL,
  CONSTRAINT users_pkey PRIMARY KEY (id)
);

CREATE SEQUENCE user_authorities_id_seq
  INCREMENT 1
  START 1
  MINVALUE 1
  MAXVALUE 2147483647
  CACHE 1;

CREATE TABLE user_authorities(
  id        integer NOT NULL DEFAULT nextval('user_authorities_id_seq'),
  user_id   integer NOT NULL,
  authority varchar(100) not null,
  CONSTRAINT user_authorities_pkey PRIMARY KEY (id)
);

然后按以下方式插入数据:

-- 创建用户:'user'
INSERT INTO users(username,password,enabled) 
VALUES('user','$2a$10$TfjwK4p4y2xn5f6RN78gwOz0Le.cMGuhNaz51WDjChGCDF9Z0yqci',true);

-- 创建用户:'admin'
INSERT INTO users(username,password,enabled) 
VALUES('admin','$2a$10$lbZgb/zt4jBoPjqF.RfsOOOKyKJMOZjFS8QMyO.5p7Ob/jzf7ASPC',true);

-- 为用户'user'创建角色'USER'
INSERT INTO user_authorities(user_id,authority) VALUES((SELECT u.id FROM users u WHERE u.username = 
'user'),'USER');

-- 为用户'admin'创建角色'ADMIN'
INSERT INTO user_authorities(user_id,authority) VALUES((SELECT u.id FROM users u WHERE u.username = 
'admin'),'ADMIN');

在Spring Boot应用程序中,我有以下安全配置:

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

   @Autowired
   DataSource dataSource;

   @Autowired
   BCryptPasswordEncoder bCryptEncoder;

   private static final String GET_USERS_SQL = "SELECT username, password, enabled FROM users WHERE       
   username = ?";

   private static final String GET_USER_AUTHORITIES_SQL = "SELECT u.username, a.authority FROM    
   user_authorities a, users u WHERE u.username = ? AND u.id = a.user_id";

   @Override
   protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       auth
           .jdbcAuthentication()        
           .usersByUsernameQuery(GET_USERS_SQL)
           .authoritiesByUsernameQuery(GET_USER_AUTHORITIES_SQL)
           .dataSource(dataSource)
           .passwordEncoder(bCryptEncoder);
   }

   @Override
   protected void configure(HttpSecurity http) throws Exception {
       http
           .httpBasic()
           .and()
           .authorizeRequests()
           .antMatchers(HttpMethod.GET, "/todo-app/userOnly").hasRole("USER")
           .antMatchers(HttpMethod.GET, "/todo-app/todos/**").hasRole("USER")
           .antMatchers(HttpMethod.GET, "/todo-app/adminOnly").hasRole("ADMIN")
           .antMatchers(HttpMethod.OPTIONS, "/**").permitAll();
   }
}

为了测试我的设置,我有一个带有以下端点的RestController:

@RestController
@RequestMapping("/todo-app")
@CrossOrigin(origins = "http://localhost:4200")
public class TodoController {

   @GetMapping("/userOnly")
   public TodoItem getForUserOnly() {
       // ...
   }

   @GetMapping("/adminOnly")
   public TodoItem getForAdminOnly() {
       // ...
   }
}

但在使用Postman进行测试时,所有测试(使用用户和管理员授权的端点)都返回403 Forbidden。

从这个情况中缺少什么?非常感谢您提供任何提示和建议。

英文:

I am setting up JDBC authentication with a PostgreSQL database from my Spring boot Security application.

I have created the below tables for users and roles, named 'users' and 'user_authorities', respectively.

<!-- language: sql -->

CREATE SEQUENCE users_id_seq
  INCREMENT 1
  START 1
  MINVALUE 1
  MAXVALUE 2147483647
  CACHE 1;

CREATE TABLE users (
  id       integer NOT NULL DEFAULT nextval(&#39;users_id_seq&#39;),
  username VARCHAR ( 100 ) UNIQUE NOT NULL,
  password VARCHAR ( 100 ) NOT NULL,
  enabled  boolean NOT NULL,
  CONSTRAINT users_pkey PRIMARY KEY (id)
);

CREATE SEQUENCE user_authorities_id_seq
  INCREMENT 1
  START 1
  MINVALUE 1
  MAXVALUE 2147483647
  CACHE 1;

  CREATE TABLE user_authorities(
   id 		  integer NOT NULL DEFAULT nextval(&#39;user_authorities_id_seq&#39;),
   user_id   integer NOT NULL,
   authority varchar(100) not null,
   CONSTRAINT user_authorities_pkey PRIMARY KEY (id)
  );

Then insert the data as below:

<!-- language: sql -->

-- create user: &#39;user&#39;
INSERT INTO users(username,password,enabled) 
VALUES(&#39;user&#39;,&#39;$2a$10$TfjwK4p4y2xn5f6RN78gwOz0Le.cMGuhNaz51WDjChGCDF9Z0yqci&#39;,true);

-- create user: &#39;admin&#39;
INSERT INTO users(username,password,enabled) 
VALUES(&#39;admin&#39;,&#39;$2a$10$lbZgb/zt4jBoPjqF.RfsOOOKyKJMOZjFS8QMyO.5p7Ob/jzf7ASPC&#39;,true);

-- create role: &#39;USER&#39; for the user: &#39;user&#39;
INSERT INTO users_authorities(user_id,authority) VALUES((select u.id from users u where u.username = 
&#39;user&#39;),&#39;USER&#39;);

-- create role: &#39;ADMIN&#39; for the user: &#39;admin&#39;
INSERT INTO user_authorities(user_id,authority) VALUES((select u.id from users u where u.username = 
&#39;admin&#39;),&#39;ADMIN&#39;);

Spring Boot application side, I have the security configuration:

package com.mi.rest.webservices.restfulwebservices.security;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{

   @Autowired
   DataSource dataSource;

   @Autowired
   BCryptPasswordEncoder bCryptEncoder;

   private static final String GET_USERS_SQL = &quot;SELECT username, password, enabled from users where       
   username = ?&quot;;

   private static final String GET_USER_AUTHORITIES_SQL = &quot;SELECT u.username, a.authority FROM    
   user_authorities a, users u WHERE u.username = ? AND u.id = a.user_id&quot;;

/**
 * Specify authentication scheme:
 * 
 * 1. In memory
 * 2. JDBC
 * 3. LDAP
 * 
 */
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {

	/**
	 auth.inMemoryAuthentication()  
   .withUser(&quot;user&quot;).password(&quot;$2a$10$TfjwK4p4y2xn5f6RN78gwOz0Le.cMGuhNaz51WDjChGCDF9Z0yqci&quot;)
   .roles(&quot;USER&quot;)
   .and()
   .withUser(&quot;admin&quot;)
   .password(&quot;$2a$10$lbZgb/zt4jBoPjqF.RfsOOOKyKJMOZjFS8QMyO.5p7Ob/jzf7ASPC&quot;)
   .roles(&quot;ADMIN&quot;);
	*/
	
	auth
	.jdbcAuthentication()		
	.usersByUsernameQuery(GET_USERS_SQL)
	.authoritiesByUsernameQuery(GET_USER_AUTHORITIES_SQL)
	.dataSource(dataSource)
	.passwordEncoder(bCryptEncoder);
}

//Authorization:
@Override
protected void configure(HttpSecurity http) throws Exception {

    http
            //HTTP Basic authentication
            .httpBasic()
            .and()
            .authorizeRequests()
            .antMatchers(HttpMethod.GET, &quot;/todo-app/userOnly&quot;).hasRole(&quot;USER&quot;)
            .antMatchers(HttpMethod.GET, &quot;/todo-app/todos/**&quot;).hasRole(&quot;USER&quot;)
            .antMatchers(HttpMethod.GET, &quot;/todo-app/adminOnly&quot;).hasRole(&quot;ADMIN&quot;)
            .antMatchers(HttpMethod.OPTIONS,&quot;/**&quot;).permitAll()
            //.and()
            //.csrf().disable()
            ;
   }

 }

Now in order to test my setup, I have a RestController with the endpoints below:

  package com.mi.rest.webservices.restfulwebservices.controllers;

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

  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.jdbc.core.JdbcTemplate;
  import org.springframework.web.bind.annotation.CrossOrigin;
  import org.springframework.web.bind.annotation.GetMapping;
  import org.springframework.web.bind.annotation.PathVariable;
  import org.springframework.web.bind.annotation.PostMapping;
  import org.springframework.web.bind.annotation.RequestBody;
  import org.springframework.web.bind.annotation.RequestMapping;
  import org.springframework.web.bind.annotation.RestController;

  @RestController
  @RequestMapping(&quot;/todo-app&quot;)
  @CrossOrigin(origins = &quot;http://localhost:4200&quot;)
  public class TodoController {	

      @GetMapping(&quot;/userOnly&quot;)
      public TodoItem getForUserOnly() {
	   TodoItem todo9 = new TodoItem();
	   todo9.setId(9);
	   todo9.setDescription(&quot;USER role item&quot;);
	   todo9.setDone(false);
	   todo9.setTargetDate(new Date());
	   todo9.setUser(&quot;user&quot;);
	
	   return todo9;
   }

   @GetMapping(&quot;/adminOnly&quot;)
   public TodoItem getForAdminOnly() {
	   TodoItem todo9 = new TodoItem();
	   todo9.setId(9);
	   todo9.setDescription(&quot;ADMIN role item&quot;);
	   todo9.setDone(false);
	   todo9.setTargetDate(new Date());
	   todo9.setUser(&quot;admin&quot;);
	
	   return todo9;
      }
  }

Testing with Postman, I keep getting 403 forbidden for all tests (with user and admin authorized endpoints).

What is missing from this picture? any hints and advises are highly appreciated.

答案1

得分: 0

请注意,我正在将 "ROLE" 附加到每个权限。Spring 要求权限具有 "ROLE...." 的前缀。

参考资料 - Spring 文档

编辑 users_authorities 表的插入语句

-- 为用户 &#39;user&#39; 创建角色:&#39;USER&#39;
INSERT INTO users_authorities(user_id,authority) VALUES((select u.id from users u where u.username = 
&#39;user&#39;),&#39;ROLE_USER&#39;);

-- 为用户 &#39;admin&#39; 创建角色:&#39;ADMIN&#39;
INSERT INTO user_authorities(user_id,authority) VALUES((select u.id from users u where u.username = 
&#39;admin&#39;),&#39;ROLE_ADMIN&#39;);
英文:

Make not that i am appending "ROLE" to each authority. Spring expects the authorities to have a prefix of "ROLE...." .

reference - Spring doc

Edit the inserts for your users_authorities table

-- create role: &#39;USER&#39; for the user: &#39;user&#39;
INSERT INTO users_authorities(user_id,authority) VALUES((select u.id from users u where u.username = 
&#39;user&#39;),&#39;ROLE_USER&#39;);

-- create role: &#39;ADMIN&#39; for the user: &#39;admin&#39;
INSERT INTO user_authorities(user_id,authority) VALUES((select u.id from users u where u.username = 
&#39;admin&#39;),&#39;ROLE_ADMIN&#39;);

huangapple
  • 本文由 发表于 2020年7月24日 18:56:02
  • 转载请务必保留本文链接:https://java.coder-hub.com/63072173.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定