共计 4671 个字符,预计需要花费 12 分钟才能阅读完成。
1。概述
Web 应用程序的一个常见要求是 在登录后将不同类型的用户重定向到不同的页面。例如,将规范用户重定向到 /homepage.html 页面和将管理员用户重定向到 /console.html 页面。
本文将展现如何应用 Spring Security 疾速平安地实现此机制。这篇文章也是建设在 Spring MVC 教程 之上的,该教程波及设置我的项目所需的核心内容。
2。Spring 平安配置
Spring Security 提供了一个组件,该组件间接负责决定在胜利验证后做什么——AuthenticationSuccessHandler。
2.1。根本配置
让咱们首先配置一个根本的 @Configuration 和 @Service 类:
@Configuration
@EnableWebSecurity
public class SecSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.authorizeRequests()
// ... endpoints
.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/homepage.html", true)
// ... other configuration
}
}
此配置中要关注的局部是 defaultSuccessUrl() 办法。胜利登录后,任何用户都将被重定向到 homepage.html。
此外,咱们须要配置用户及其角色。出于本文的目标,咱们将实现一个简略的UserDetailService,其中有两个用户,每个用户都有一个角色。无关此主题的更多信息,请浏览咱们的文章 Spring Security — Roles and Privileges。
@Service
public class MyUserDetailsService implements UserDetailsService {private Map<String, User> roles = new HashMap<>();
@PostConstruct
public void init() {roles.put("admin2", new User("admin", "{noop}admin1", getAuthority("ROLE_ADMIN")));
roles.put("user2", new User("user", "{noop}user1", getAuthority("ROLE_USER")));
}
@Override
public UserDetails loadUserByUsername(String username) {return roles.get(username);
}
private List<GrantedAuthority> getAuthority(String role) {return Collections.singletonList(new SimpleGrantedAuthority(role));
}
}
另外请留神,在这个简略的示例中,咱们不会应用明码编码器。
2.2。增加自定义胜利处理程序
咱们当初有两个具备两个不同角色的用户:user 和 admin。胜利登录后,两者都将被重定向到 hompeage.html。让咱们看看如何依据用户的角色进行不同的重定向。
首先,咱们须要将自定义胜利处理程序定义为 bean:
@Bean
public AuthenticationSuccessHandler myAuthenticationSuccessHandler(){return new MySimpleUrlAuthenticationSuccessHandler();
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.authorizeRequests()
// endpoints
.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/login")
.successHandler(myAuthenticationSuccessHandler())
// other configuration
}
2.3。XML 配置
在查看咱们的自定义胜利处理程序的实现之前,咱们还要查看等价的 XML 配置:
<http use-expressions="true" >
<!-- other configuration -->
<form-login login-page='/login.html'
authentication-failure-url="/login.html?error=true"
authentication-success-handler-ref="myAuthenticationSuccessHandler"/>
<logout/>
</http>
<beans:bean id="myAuthenticationSuccessHandler"
class="com.baeldung.security.MySimpleUrlAuthenticationSuccessHandler" />
<authentication-manager>
<authentication-provider>
<user-service>
<user name="user1" password="{noop}user1Pass" authorities="ROLE_USER" />
<user name="admin1" password="{noop}admin1Pass" authorities="ROLE_ADMIN" />
</user-service>
</authentication-provider>
</authentication-manager>
3。自定义身份验证胜利处理程序
除了 AuthenticationSuccessHandler 接口,Spring 还为这个策略组件提供了一个正当的默认值 – AbstractAuthenticationTargetUrlRequestHandler 和一个简略的实现 – SimpleUrlAuthenticationSuccessHandler。通常,这些实现将在登录后确定 URL 并执行到该 URL 的重定向。
尽管有些灵便,但确定此指标 URL 的机制不容许以编程形式进行确定——因而咱们将实现接口并提供胜利处理程序的自定义实现。此实现将依据用户的角色确定用户登录后重定向到的 URL。
首先,咱们须要重写 onAuthenticationSuccess 办法:
public class MySimpleUrlAuthenticationSuccessHandler
implements AuthenticationSuccessHandler {protected Log logger = LogFactory.getLog(this.getClass());
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException {handle(request, response, authentication);
clearAuthenticationAttributes(request);
}
咱们自定义的办法调用了两个辅助办法:
protected void handle(
HttpServletRequest request,
HttpServletResponse response,
Authentication authentication
) throws IOException {String targetUrl = determineTargetUrl(authentication);
if (response.isCommitted()) {
logger.debug(
"Response has already been committed. Unable to redirect to"
+ targetUrl);
return;
}
redirectStrategy.sendRedirect(request, response, targetUrl);
}
以下办法执行理论工作并将用户映射到指标 URL:
protected String determineTargetUrl(final Authentication authentication) {Map<String, String> roleTargetUrlMap = new HashMap<>();
roleTargetUrlMap.put("ROLE_USER", "/homepage.html");
roleTargetUrlMap.put("ROLE_ADMIN", "/console.html");
final Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
for (final GrantedAuthority grantedAuthority : authorities) {String authorityName = grantedAuthority.getAuthority();
if(roleTargetUrlMap.containsKey(authorityName)) {return roleTargetUrlMap.get(authorityName);
}
}
throw new IllegalStateException();}
请留神,此办法将返回用户领有的第一个角色的映射 URL。因而,如果用户有多个角色,映射的 URL 将与 authorities 汇合中给出的第一个角色匹配。
protected void clearAuthenticationAttributes(HttpServletRequest request) {HttpSession session = request.getSession(false);
if (session == null) {return;}
session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
}
determineTargetUrl – 这是策略的外围 – 只需查看用户类型(由权限确定)并 依据此角色抉择指标 URL。
因而,admin 用户 – 由 ROLE_ADMIN 权限确定 – 将在登录后重定向到控制台页面,而 规范用户 – 由 ROLE_USER 确定 – 将是重定向到主页。
4。论断
本文中提及的代码 [在 GitHub 上] (https://github.com/eugenp/tut…) 可用。这是一个基于 Maven 的我的项目,因而它应该很容易导入和运行。