如何使用 Jersey rest 修复 Spring 安全和 Spring 数据 JPA 中禁止的 403
How to fix 403 forbidden in Spring security and Spring data JPA with Jersey rest
我从 rest api 收到 403 Forbidden,它正在使用 Spring 安全的 JDBC 身份验证。
我已经使用带有 Spring 启动的 Jersey 编写了简单的 restful api,并尝试使用 inMemoryAuthentication()
方法实现 Spring 安全性并且工作正常。但是当我切换到 jdbcAuthentication()
方法时,我得到 403 禁止,因为我使用邮递员的有效凭据点击服务。我不明白我哪里做错了。
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
DataSource dataSource;
@Override
protected void configure(HttpSecurity http) throws Exception{
http.csrf().disable()
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/jersey/**").hasRole("USER")
.antMatchers("/console/**").permitAll()
.and()
.headers().frameOptions().disable();
//.anyRequest().permitAll();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.authoritiesByUsernameQuery("select USERNAME, ROLE from EMPLOYEE where USERNAME=?")
.usersByUsernameQuery("select USERNAME, PASSWORD , 1 as enabled from EMPLOYEE where USERNAME=?");
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
data.sql
INSERT INTO EMPLOYEE VALUES ('lalit','a$TV//Fu/4UwMTIqnPbkahqeMNjrrF1YQT1MdEwNDvaHurH5wR7ZLnm','USER');
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
更新
error log:
2019-05-24 19:46:21.703 DEBUG 11724 --- [nio-8088-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@f9c70a69: Principal: org.springframework.security.core.userdetails.User@61fa502: Username: lalit; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: USER
2019-05-24 19:46:21.706 DEBUG 11724 --- [nio-8088-exec-2] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@4a78101b, returned: -1
2019-05-24 19:46:21.713 DEBUG 11724 --- [nio-8088-exec-2] o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is not anonymous); delegating to AccessDeniedHandler
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:124) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
...
这是我使用有效凭据点击服务时得到的结果。
HTTP 状态 403 – 禁止
您收到 403 Forbidden,因为 Spring 安全人员在访问具有 /jersey/
.[=12= 的任何映射时可能在数据库中找到了与角色 "ROLE_USER" 不同的角色]
也看看下面的配置。可能是需要添加的密码编码器。
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.passwordEncoder(passwordEncoder())
.authoritiesByUsernameQuery("select USERNAME, ROLE from EMPLOYEE where USERNAME=?")
.usersByUsernameQuery("select USERNAME, PASSWORD , 1 as enabled from EMPLOYEE where USERNAME=?");
}
更新
将数据库中的角色保存为 "ROLE_USER" 而不是 "USER"
由于您的错误日志显示凭据之前已经过身份验证,您需要在尝试再次登录之前删除浏览器的 cookie,或者只打开一个新的隐身选项卡。
我从 rest api 收到 403 Forbidden,它正在使用 Spring 安全的 JDBC 身份验证。
我已经使用带有 Spring 启动的 Jersey 编写了简单的 restful api,并尝试使用 inMemoryAuthentication()
方法实现 Spring 安全性并且工作正常。但是当我切换到 jdbcAuthentication()
方法时,我得到 403 禁止,因为我使用邮递员的有效凭据点击服务。我不明白我哪里做错了。
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
DataSource dataSource;
@Override
protected void configure(HttpSecurity http) throws Exception{
http.csrf().disable()
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/jersey/**").hasRole("USER")
.antMatchers("/console/**").permitAll()
.and()
.headers().frameOptions().disable();
//.anyRequest().permitAll();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.authoritiesByUsernameQuery("select USERNAME, ROLE from EMPLOYEE where USERNAME=?")
.usersByUsernameQuery("select USERNAME, PASSWORD , 1 as enabled from EMPLOYEE where USERNAME=?");
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
data.sql
INSERT INTO EMPLOYEE VALUES ('lalit','a$TV//Fu/4UwMTIqnPbkahqeMNjrrF1YQT1MdEwNDvaHurH5wR7ZLnm','USER');
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
更新
error log:
2019-05-24 19:46:21.703 DEBUG 11724 --- [nio-8088-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@f9c70a69: Principal: org.springframework.security.core.userdetails.User@61fa502: Username: lalit; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: USER
2019-05-24 19:46:21.706 DEBUG 11724 --- [nio-8088-exec-2] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@4a78101b, returned: -1
2019-05-24 19:46:21.713 DEBUG 11724 --- [nio-8088-exec-2] o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is not anonymous); delegating to AccessDeniedHandler
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:124) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
...
这是我使用有效凭据点击服务时得到的结果。
HTTP 状态 403 – 禁止
您收到 403 Forbidden,因为 Spring 安全人员在访问具有 /jersey/
.[=12= 的任何映射时可能在数据库中找到了与角色 "ROLE_USER" 不同的角色]
也看看下面的配置。可能是需要添加的密码编码器。
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.passwordEncoder(passwordEncoder())
.authoritiesByUsernameQuery("select USERNAME, ROLE from EMPLOYEE where USERNAME=?")
.usersByUsernameQuery("select USERNAME, PASSWORD , 1 as enabled from EMPLOYEE where USERNAME=?");
}
更新
将数据库中的角色保存为 "ROLE_USER" 而不是 "USER"
由于您的错误日志显示凭据之前已经过身份验证,您需要在尝试再次登录之前删除浏览器的 cookie,或者只打开一个新的隐身选项卡。