栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Spring Security 3.2.1具有不同WebSecurityConfigurerAdapters的多个登录表单

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Security 3.2.1具有不同WebSecurityConfigurerAdapters的多个登录表单

我针对多个登录页面使用的解决方案涉及单个http身份验证,但我提供了自己的实现

  • AuthenticationEntryPoint
  • AuthenticationFailureHandler
  • LogoutSuccessHandler

我需要这些实现能够根据请求路径中的令牌进行切换。

在我的网站中,URL中带有客户令牌的页面受到保护,并要求用户在customer_signin页面上以CUSTOMER身份进行身份验证。因此,如果要转到页面/
customer /
home,则需要先重定向到customer_signin页面以进行身份​​验证。如果我无法通过customer_signin进行身份验证,则应将我带错误参数返回到customer_signin。这样就可以显示一条消息。
当我成功通过身份验证为CUSTOMER并希望注销后,LogoutSuccessHandler应将我带回到customer_signin页面。


对于管理员需要在admin_signin页面进行身份验证以访问URL中带有管理令牌的页面,我也有类似的要求。

首先,我定义了一个类,使我可以获取令牌列表(每种登录页面类型一个)

public class PathTokens {    private final List<String> tokens = new ArrayList<>();    public PathTokens(){};    public PathTokens(final List<String> tokens) {      this.tokens.addAll(tokens);    }    public boolean isTokenInPath(String path) {      if (path != null) {        for (String s : tokens) { if (path.contains(s)) {     return true; }        }      }      return false;    }    public String getTokenFromPath(String path) {      if (path != null) {          for (String s : tokens) {   if (path.contains(s)) {       return s;   }          }      }      return null;  }  public List<String> getTokens() {      return tokens;  }}

然后,我

PathLoginAuthenticationEntryPoint
根据请求uri中的令牌使用它来更改登录URL。

@Componentpublic class PathLoginAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {    private final PathTokens tokens;    @Autowired    public PathLoginAuthenticationEntryPoint(PathTokens tokens) {        //  LoginUrlAuthenticationEntryPoint requires a default        super("/");        this.tokens = tokens;    }        @Override    protected String determineUrlToUseForThisRequest(HttpServletRequest request, HttpServletResponse response,     AuthenticationException exception) {       return getLoginUrlFromPath(request);    }    private String getLoginUrlFromPath(HttpServletRequest request) {        String requestUrl = request.getRequestURI();        if (tokens.isTokenInPath(requestUrl)) { return "/" + tokens.getTokenFromPath(requestUrl) + "_signin";        }        throw new PathTokenNotFoundException("Token not found in request URL " + requestUrl + " when retrieving LoginUrl for login form");    }}

PathTokenNotFoundException扩展了AuthenticationException,以便您可以按常规方式处理它。

public class PathTokenNotFoundException extends AuthenticationException {   public PathTokenNotFoundException(String msg) {       super(msg);    }    public PathTokenNotFoundException(String msg, Throwable t) {       super(msg, t);    }}

接下来,我提供一种实现方法,

AuthenticationFailureHandler
该方法查看请求标头中的引荐来源网址,以确定将用户定向到哪个登录错误页面。

@Componentpublic class PathUrlAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {    private final PathTokens tokens;    @Autowired    public PathUrlAuthenticationFailureHandler(PathTokens tokens) {        super();        this.tokens = tokens;    }        @Override    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,   AuthenticationException exception) throws IOException, ServletException {        setDefaultFailureUrl(getFailureUrlFromPath(request));        super.onAuthenticationFailure(request, response, exception);    }    private String getFailureUrlFromPath(HttpServletRequest request) {        String refererUrl = request.getHeader("Referer");        if (tokens.isTokenInPath(refererUrl)) { return "/" + tokens.getTokenFromPath(refererUrl) + "_signin?error=1";        }        throw new PathTokenNotFoundException("Token not found in referer URL " + refererUrl + " when retrieving failureUrl for login form");    }}

接下来,我提供一个实现的实现,

LogoutSuccessHandler
该实现将注销用户并将其重定向到正确的登录页面,具体取决于请求标头中引用网址中的令牌。

@Componentpublic class PathUrlLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {    private final PathTokens tokens;    @Autowired    public PathUrlLogoutSuccessHandler(PathTokens tokens) {        super();        this.tokens = tokens;    }    @Override    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)        throws IOException, ServletException {        setDefaultTargetUrl(getTargetUrlFromPath(request));        setAlwaysUseDefaultTargetUrl(true);        handle(request, response, authentication);    }    private String getTargetUrlFromPath(HttpServletRequest request) {        String refererUrl = request.getHeader("Referer");        if (tokens.isTokenInPath(refererUrl)) { return "/" + tokens.getTokenFromPath(refererUrl) + "_signin";        }        throw new PathTokenNotFoundException("Token not found in referer URL " + refererUrl + " when retrieving logoutUrl.");    } }

最后一步是在安全配置中将它们全部连接在一起。

@Configuration@EnableWebSecurity@EnableGlobalMethodSecurity(prePostEnabled = true)public class SecurityConfig extends WebSecurityConfigurerAdapter {    @Autowired PathLoginAuthenticationEntryPoint loginEntryPoint;    @Autowired PathUrlAuthenticationFailureHandler loginFailureHandler;    @Autowired    PathUrlLogoutSuccessHandler logoutSuccessHandler;    @Bean    public PathTokens pathTokens(){        return new PathTokens(Arrays.asList("customer", "admin"));    }    @Autowired    public void registerGlobalAuthentication(        AuthenticationManagerBuilder auth) throws Exception {        auth .inMemoryAuthentication() .withUser("customer").password("password").roles("CUSTOMER").and() .withUser("admin").password("password").roles("ADMIN");    }    @Override    public void configure(WebSecurity web) throws Exception {        web .ignoring() .antMatchers("/", "/signin/**", "/error/**", "/templates/**", "/resources/**", "/webjars/**");    }    @Override    protected void configure(HttpSecurity http) throws Exception {http .csrf().disable() .authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .antMatchers("/customer/**").hasRole("CUSTOMER") .and() .formLogin() .loginProcessingUrl("/j_spring_security_check") .usernameParameter("j_username").passwordParameter("j_password") .failureHandler(loginFailureHandler);        http.logout().logoutSuccessHandler(logoutSuccessHandler);        http.exceptionHandling().authenticationEntryPoint(loginEntryPoint);        http.exceptionHandling().accessDeniedPage("/accessDenied");    }}

配置完成后,您需要一个控制器来定向到实际的登录页面。下面的SigninControiller检查queryString中是否有指示登录错误的值,然后设置用于控制错误消息的属性。

@Controller@SessionAttributes("userRoles")public class SigninController {    @RequestMapping(value = "customer_signin", method = RequestMethod.GET)    public String customerSignin(Model model, HttpServletRequest request) {        Set<String> userRoles = AuthorityUtils.authorityListToSet(SecurityContextHolder.getContext().getAuthentication().getAuthorities());        model.addAttribute("userRole", userRoles);        if(request.getQueryString() != null){ model.addAttribute("error", "1");        }        return "signin/customer_signin";    }    @RequestMapping(value = "admin_signin", method = RequestMethod.GET)    public String adminSignin(Model model, HttpServletRequest request) {    Set<String> userRoles = AuthorityUtils.authorityListToSet(SecurityContextHolder.getContext().getAuthentication().getAuthorities());        model.addAttribute("userRole", userRoles);        if(request.getQueryString() != null){ model.addAttribute("error", "1");        }        return "signin/admin_signin";    }}


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/435529.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号