英文:
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('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)
);
Then insert the data as below:
<!-- language: sql -->
-- create user: 'user'
INSERT INTO users(username,password,enabled)
VALUES('user','$2a$10$TfjwK4p4y2xn5f6RN78gwOz0Le.cMGuhNaz51WDjChGCDF9Z0yqci',true);
-- create user: 'admin'
INSERT INTO users(username,password,enabled)
VALUES('admin','$2a$10$lbZgb/zt4jBoPjqF.RfsOOOKyKJMOZjFS8QMyO.5p7Ob/jzf7ASPC',true);
-- create role: 'USER' for the user: 'user'
INSERT INTO users_authorities(user_id,authority) VALUES((select u.id from users u where u.username =
'user'),'USER');
-- create role: 'ADMIN' for the user: 'admin'
INSERT INTO user_authorities(user_id,authority) VALUES((select u.id from users u where u.username =
'admin'),'ADMIN');
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 = "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";
/**
* Specify authentication scheme:
*
* 1. In memory
* 2. JDBC
* 3. LDAP
*
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
/**
auth.inMemoryAuthentication()
.withUser("user").password("$2a$10$TfjwK4p4y2xn5f6RN78gwOz0Le.cMGuhNaz51WDjChGCDF9Z0yqci")
.roles("USER")
.and()
.withUser("admin")
.password("$2a$10$lbZgb/zt4jBoPjqF.RfsOOOKyKJMOZjFS8QMyO.5p7Ob/jzf7ASPC")
.roles("ADMIN");
*/
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, "/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()
//.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("/todo-app")
@CrossOrigin(origins = "http://localhost:4200")
public class TodoController {
@GetMapping("/userOnly")
public TodoItem getForUserOnly() {
TodoItem todo9 = new TodoItem();
todo9.setId(9);
todo9.setDescription("USER role item");
todo9.setDone(false);
todo9.setTargetDate(new Date());
todo9.setUser("user");
return todo9;
}
@GetMapping("/adminOnly")
public TodoItem getForAdminOnly() {
TodoItem todo9 = new TodoItem();
todo9.setId(9);
todo9.setDescription("ADMIN role item");
todo9.setDone(false);
todo9.setTargetDate(new Date());
todo9.setUser("admin");
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
表的插入语句
-- 为用户 'user' 创建角色:'USER'
INSERT INTO users_authorities(user_id,authority) VALUES((select u.id from users u where u.username =
'user'),'ROLE_USER');
-- 为用户 'admin' 创建角色:'ADMIN'
INSERT INTO user_authorities(user_id,authority) VALUES((select u.id from users u where u.username =
'admin'),'ROLE_ADMIN');
英文:
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: 'USER' for the user: 'user'
INSERT INTO users_authorities(user_id,authority) VALUES((select u.id from users u where u.username =
'user'),'ROLE_USER');
-- create role: 'ADMIN' for the user: 'admin'
INSERT INTO user_authorities(user_id,authority) VALUES((select u.id from users u where u.username =
'admin'),'ROLE_ADMIN');
专注分享java语言的经验与见解,让所有开发者获益!
评论