我正在努力启动 Spring Boot 应用程序并运行安全功能。我在让它运行时遇到一些困难,因为我创建了其他问题。然而,这个问题有点在功能方面。我有多个角色,例如管理员和客户,登录后我想将它们发送到各自的在线页面。我想到的一种方法是创建一个登录页面,然后使用 cookie 重定向它们,尽管我不知道该怎么做。如果我的方法正确或者 Spring Boot 提供了默认功能,您能否提供任何示例,请告诉我。
这是我的 SecurityConfig 类:
package com.crossover.techtrial.java.se.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
private DataSource dataSource;
@Value("${spring.queries.users-query}")
private String usersQuery;
@Value("${spring.queries.roles-query}")
private String rolesQuery;
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception
{
auth.
jdbcAuthentication()
.usersByUsernameQuery(usersQuery)
.authoritiesByUsernameQuery(rolesQuery)
.dataSource(dataSource)
.passwordEncoder(bCryptPasswordEncoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.
authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/registration").permitAll()
.antMatchers("/app/*").hasAnyAuthority("ADMIN", "CUSTOMER")
.antMatchers("/admin/**").hasAuthority("ADMIN").anyRequest()
.authenticated().and().csrf().disable().formLogin()
.loginPage("/login").failureUrl("/login?error=true")
.defaultSuccessUrl("/home")
.usernameParameter("username")
.passwordParameter("password")
.and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/").and().exceptionHandling()
.accessDeniedPage("/access-denied");
}
@Override
public void configure(WebSecurity web) throws Exception
{
web
.ignoring()
.antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**");
}
}
编辑:
正如 dur 所指出的,我可能需要做这样的事情:
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
HttpSession session = httpServletRequest.getSession();
User authUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
session.setAttribute("username", authUser.getUsername());
//set our response to OK status
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
// Now I need to redirect the user based on his role.
httpServletResponse.sendRedirect("home");
}
}
现在的问题是如何从 authUser 获取角色名称。我希望我做得对,不需要做任何其他事情。其次,我如何将这个成功的处理程序适合我的 SecurityConfig 类。请突出显示需要完成的更改。
最佳答案
正如 @dur 建议的那样,我通过添加 CustomSuccessHandler 解决了这个问题:
@Component
@Configuration
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler
{
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, Authentication authentication)
throws IOException, ServletException, RuntimeException
{
HttpSession session = httpServletRequest.getSession();
User authUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
session.setAttribute("username", authUser.getUsername());
//set our response to OK status
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
authorities.forEach(authority ->
{
if(authority.getAuthority().equals("ADMIN_ROLE"))
{
session.setAttribute("role", AppRole.ADMIN);
try
{
//since we have created our custom success handler, its up to us to where
//we will redirect the user after successfully login
httpServletResponse.sendRedirect("/admin/home");
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
else if (authority.getAuthority().equals("CUSTOMER_ROLE"))
{
session.setAttribute("role", AppRole.CUSTOMER);
try
{
//since we have created our custom success handler, its up to us to where
//we will redirect the user after successfully login
httpServletResponse.sendRedirect("/user/home");
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
});
}
}
我通过配置添加了这个:
http.
authorizeRequests()
.antMatchers("/user/**").hasAuthority("CUSTOMER_ROLE")
.antMatchers("/admin/**").hasAuthority("ADMIN_ROLE").anyRequest()
.authenticated().and().csrf().disable().formLogin()
.loginPage("/login").failureUrl("/login?error=true")
.successHandler(successHandler) // successHandler is a reference to my CustomAuthenticationSuccessHandler
....
关于java - Spring Security 中不同角色的多个主页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44046154/