为啥spring security hasRole函数不认证任何api
Posted
技术标签:
【中文标题】为啥spring security hasRole函数不认证任何api【英文标题】:why spring security hasRole function does not authenticate any apis为什么spring security hasRole函数不认证任何api 【发布时间】:2020-02-29 11:58:53 【问题描述】:我在使用spring security hasRole
时遇到了一些麻烦。我在数据库中有 2 个角色保存为 ROLE_ADMIN 和 ROLE_USER。我想允许一些具有 ADMIN 角色的 API,一些具有 USER 角色的 API。这是我的代码。
安全配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
private DataSource dataSource;
@Value("$spring.queries.users-query")
private String usersQuery;
@Value("$spring.queries.roles-query")
private String rolesQuery;
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception
auth
.jdbcAuthentication()
.dataSource(dataSource)
.passwordEncoder(bCryptPasswordEncoder())
.usersByUsernameQuery(usersQuery)
.authoritiesByUsernameQuery(rolesQuery);
@Override
protected void configure(HttpSecurity http)
System.out.println("configure " );
try
http.csrf().disable().authorizeRequests()
.antMatchers("/", "/*.html").permitAll()
.antMatchers("/home").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/profile/").hasAnyRole("ADMIN","USER")
.antMatchers("/admin/*").hasRole("ADMIN")
.antMatchers("/insurance/*").hasRole("ADMIN")
.antMatchers("/company/*").hasRole("ADMIN")
.anyRequest().authenticated();
catch (Exception e)
e.printStackTrace();
@Override
public void configure(WebSecurity web)
web.httpFirewall(allowUrlEncodedSlashHttpFirewall())
.ignoring()
.antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**", "/templates/**");
@Bean
public HttpFirewall allowUrlEncodedSlashHttpFirewall()
StrictHttpFirewall firewall = new StrictHttpFirewall();
/*firewall.setAllowUrlEncodedSlash(true);
firewall.setAllowSemicolon(true);*/
firewall.setAllowUrlEncodedDoubleSlash(true);
return firewall;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder()
return new BCryptPasswordEncoder();
我在application.properties
中有sql queries
spring.queries.users-query=select username, password, status from insurance.users where username=?
spring.queries.roles-query=select u.username, r.role from insurance.users u inner join insurance.roles r on(u.role_id=r.id) where u.username=?
问题是当我尝试登录时,我收到 403 错误代码。
这里是Controller.class
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(@RequestParam(value = "email") String email,
@RequestParam(value = "password") String password, HttpSession session)
Result result = userService.login(email, password);
session.setAttribute("user", result.getData());
if(result.getStatus() == 200)
return "redirect:/profile";
else
return "redirect:/login?error";
@RequestMapping(value = "/profile", method = RequestMethod.GET)
public String profile(HttpSession httpSession, Model model)
if(httpSession.getAttribute("user") != null)
UserResponse user = (UserResponse) httpSession.getAttribute("user");
model.addAttribute("user", user);
return "profile";
else
return "redirect:/home";
我试图解决它,但找不到。如果您有任何建议,请告诉。
我按照建议更改了我的配置文件。我添加了自定义登录逻辑,现在当我想去 /admins 或其他 url 时,我 重定向到登录 url 这是我的配置代码
protected void configure(HttpSecurity http)
try
http.csrf().disable()
.authorizeRequests()
.antMatchers("/home").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/insurance/*").hasRole("ADMIN")
.antMatchers("/company/*").hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/login.html").permitAll().usernameParameter("username") .passwordParameter("password")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/profile.html", true);
catch (Exception e)
e.printStackTrace();
【问题讨论】:
您有自己的登录名,不要。 Spring Security 应该解决这个问题。您有规则,但 Spring Security 永远不会看到登录用户,因为该过程完全绕过 Spring Security。 @M.Deinum,你能再看看我的代码吗。我按照你说的更新了 从您的配置方法中删除try/catch
。同样,如果不设置身份验证管理器,它也不会做任何事情。
【参考方案1】:
只需在身份验证例外中添加登录名即可。 试试这个
protected void configure(HttpSecurity http)
try
http.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/home").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/insurance/*").hasRole("ADMIN")
.antMatchers("/company/*").hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/login.html").permitAll().usernameParameter("username") .passwordParameter("password")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/profile.html", true);
catch (Exception e)
e.printStackTrace();
【讨论】:
您建议使用哪种登录方式?对不起,我没听懂您的意思 我说的是 .antMatchers("/login").permitALL() 基本上您需要删除登录 API 本身的身份验证才能使用它进行身份验证(因为您当时尚未经过身份验证) 我按照你说的删除了登录部分,仍然没有运气。不过谢谢 我要求您将登录部分添加到全部许可中以上是关于为啥spring security hasRole函数不认证任何api的主要内容,如果未能解决你的问题,请参考以下文章
如何正确使用 Spring Security 中的 hasRole?
如何对 Spring Security @PreAuthorize(hasRole) 进行单元测试?
Spring Security 中的 hasRole() 无法正常工作 [重复]
Spring Security 'Roles' 和 'Privileges' 和 Thymeleaf 'hasRole' 和 'hasAuthority'