SpringSecurity学习 - 登录之后的重定向
简介
通常一个后台管理系统,会包含不同的角色和权限;
然后不同的角色,登录后会根据权限的不同,跳转到不同的界面;
这里我们还是设定有两个角色:普通用户和管理员;
普通用户:登录成功跳转到 home 页面;
管理员:登录成功跳转到 admin 页面;
目录
基本配置
配置用户和角色
创建处理器类
配置处理器
修改控制器
运行
正文
1. 基本配置
先配置一个默认的登录成功界面,如下所示:
@Configuration @EnableWebSecurity @Slf4j public class SecSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .formLogin() .loginPage("/login") // 登录成功跳转的页面,第二个参数true表示每次登录成功都是跳转到home,如果false则表示跳转到登录之前访问的页面 .defaultSuccessUrl("/home.html", true) // ... 其他配置 } } 复制代码
这样当用户登录成功后,会默认跳转到home.html界面;
但是本节我们要做的就是修改这个地方,使得不同角色跳转不到不同的界面;
下面开始进入主体
2. 配置用户和角色
这里我们用 全局配置:
@Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { // 数据没有持久化,只是保存在内存中 auth.inMemoryAuthentication() .withUser("javalover").password(passwordEncoder().encode("123456")).roles("USER") .and() .withUser("admin").password(passwordEncoder().encode("123456")).roles("ADMIN"); } 复制代码
这里配置了两个用户:
普通用户:javalover
管理员:admin
3. 创建处理器类
第一步中的配置是:两个角色登录后,默认都是跳转到home.html
界面;
接下来就开始修改,使他们跳转到不同的界面;
先定义一个处理器类,实现了AuthenticationSuccessHandler
接口:
public class MySimpleUrlAuthenticationSuccessHandler implements AuthenticationSuccessHandler { private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); @Override public void onAuthenticationSuccess(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); } } 复制代码
覆写的onAuthenticationSuccess
方法:登录成功会先到这个地方,然后我们就可以在这里控制下一步要跳转的界面(当然其他的一些操作也可以);
determineTargetUrl
方法:就是这篇文章的核心;
它会根据不同的权限,获取到不同的跳转url,然后重定向;
protected String determineTargetUrl(final Authentication authentication) { Map<String, String> roleTargetUrlMap = new HashMap<>(); roleTargetUrlMap.put("ROLE_USER", "/home"); roleTargetUrlMap.put("ROLE_ADMIN", "/admin"); 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(); } 复制代码
4. 配置处理器
上面我们定义了一个处理器,用来控制登录成功后的跳转界面;
这里我们将其配置到config类中;
先在配置类中注入一个Bean:AuthenticationSuccessHandler
,返回的是刚才创建的处理器类
@Bean public AuthenticationSuccessHandler myAuthenticationSuccessHandler(){ return new MySimpleUrlAuthenticationSuccessHandler(); } 复制代码
然后替换掉开头设置的跳转url参数,如下所示:
@Override protected void configure(final HttpSecurity http) throws Exception { http .authorizeRequests() .formLogin() .loginPage("/login") .successHandler(myAuthenticationSuccessHandler()) // ...其他配置 } 复制代码
5. 修改控制器
上面我们跳转home和admin,是通过控制器进行跳转的,下面我们配置一下控制器:
@Controller @Slf4j public class SecurityController { @RequestMapping("/login") public String login(){ log.info("=== login ==="); return "login"; } @RequestMapping("/home") public String home(Model model){ model.addAttribute("user", getUsername()); model.addAttribute("role", getAuthority()); return "home"; } @RequestMapping("/admin") public String admin(Model model){ model.addAttribute("user", getUsername()); model.addAttribute("role", getAuthority()); return "admin"; } @RequestMapping("/accessDenied") public String accessDenied(Model model){ model.addAttribute("user", getUsername()); model.addAttribute("role", getAuthority()); return "access_denied"; } // 获取当前登录的用户名 private String getUsername(){ return SecurityContextHolder.getContext().getAuthentication().getName(); } // 获取当前登录的用户角色 private String getAuthority(){ Collection<? extends GrantedAuthority> authorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities(); ArrayList<String> list = new ArrayList<>(); for(GrantedAuthority authority: authorities){ list.add(authority.getAuthority()); } log.info("=== authority:" + list); return list.toString(); } } 复制代码
6. 运行
接下来我们就可以启动程序,访问http://localhost:8090/
进行测试了
前端代码就不贴了,就是三个界面:login,.html, home.html, admin.html。完整源码见文末
普通用户登录:
跳转到home
管理员登录:
跳转到admin
总结
重定向的核心就是那个处理器中的determineTargetUrl
方法,根据角色的不同,跳转到不同的界面;
作者:汤圆学Java
链接:https://juejin.cn/post/7032566211414065159