整合Spring Security进行自定义用户登录控制功能实现·
<div class="log"> <div class="am-g"> <div class="am-u-lg-3 am-u-md-6 am-u-sm-8 am-u-sm-centered log-content"> <h1 class="log-title am-animation-slide-top" style="color: black;" th:text="#{login.welcomeTitle}">~欢迎登录博客~</h1> <br> <div th:if="${param.error}" style="color: red" th:text="#{login.error}">用户名或密码错误!</div> <form class="am-form" id="loginForm" th:action="@{/login}" method="post"> <div> <input type="hidden" name="url" th:value="${url}"> </div> <div class="am-input-group am-radius am-animation-slide-left"> <input type="text" class="am-radius" th:placeholder="#{login.username}" name="username" maxlength="8" /> <span class="am-input-group-label log-icon am-radius"> <i class="am-icon-user am-icon-sm am-icon-fw"></i> </span> </div> <br> <div class="am-input-group am-animation-slide-left log-animation-delay"> <input type="password" class="am-form-field am-radius log-input" th:placeholder="#{login.password}" name="password" maxlength="10" /> <span class="am-input-group-label log-icon am-radius"> <i class="am-icon-lock am-icon-sm am-icon-fw"></i> </span> </div> <label> <input type="checkbox" name="rememberme"> 记住我 </label> <div style="padding-top: 10px;"> <input type="submit" th:value="#{login.sub}" class="am-btn am-btn-primary am-btn-block am-btn-lg am-radius am-animation-slide-bottom log-animation-delay" /> </div> </form> </div> </div>
@Controller public class LoginController { // 向登录页面跳转,同时封装原始页面地址 @GetMapping(value = "/login") public String login(HttpServletRequest request, Map map) { // 分别获取请求头和参数url中的原始访问路径 String referer = request.getHeader("Referer"); String url = request.getParameter("url"); System.out.println("referer= " + referer); System.out.println("url= " + url); // 如果参数url中已经封装了原始页面路径,直接返回该路径 if (url != null && !url.equals("")) { map.put("url", url); // 如果请求头本身包含登录,将重定向url设为空,让后台通过用户角色进行选择跳转 } else if (referer != null && referer.contains("/login")) { map.put("url", ""); } else { // 否则的话,就记住请求头中的原始访问路径 map.put("url", referer); } return "comm/login"; } // 对Security拦截的无权限访问异常处理路径映射 @GetMapping(value = "/errorPage/{page}/{code}") public String AccessExecptionHandler(@PathVariable("page") String page, @PathVariable("code") String code) { return page + "/" + code; } }
@EnableWebSecurity // 开启MVC security安全支持 public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private DataSource dataSource; @Value("${COOKIE.VALIDITY}") private Integer COOKIE_VALIDITY; /** * 重写configure(AuthenticationManagerBuilder auth)方法,进行自定义用户认证 * @param auth * @throws Exception */ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // 密码需要设置编码器 BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); // 使用JDBC进行身份认证 String userSQL ="select username,password,valid from t_user where username = ?"; String authoritySQL ="select u.username,a.authority from t_user u,t_authority a," + "t_user_authority ua where ua.user_id=u.id " + "and ua.authority_id=a.id and u.username =?"; auth.jdbcAuthentication().passwordEncoder(encoder) .dataSource(dataSource) .usersByUsernameQuery(userSQL) .authoritiesByUsernameQuery(authoritySQL); } /** * 重写configure(HttpSecurity http)方法,进行用户授权管理 * @param http * @throws Exception */ @Override protected void configure(HttpSecurity http) throws Exception { // 1、自定义用户访问控制 http.authorizeRequests() .antMatchers("/","/page/**","/article/**","/login").permitAll() .antMatchers("/back/**","/assets/**","/user/**","/article_img/**").permitAll() .antMatchers("/admin/**").hasRole("admin") .anyRequest().authenticated(); // 2、自定义用户登录控制 http.formLogin() .loginPage("/login") .usernameParameter("username").passwordParameter("password") .successHandler(new AuthenticationSuccessHandler() { @Override public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { String url = httpServletRequest.getParameter("url"); // 获取被拦截的原始访问路径 RequestCache requestCache = new HttpSessionRequestCache(); SavedRequest savedRequest = requestCache.getRequest(httpServletRequest,httpServletResponse); if(savedRequest !=null){ // 如果存在原始拦截路径,登录成功后重定向到原始访问路径 httpServletResponse.sendRedirect(savedRequest.getRedirectUrl()); } else if(url != null && !url.equals("")){ // 跳转到之前所在页面 URL fullURL = new URL(url); httpServletResponse.sendRedirect(fullURL.getPath()); }else { // 直接登录的用户,根据用户角色分别重定向到后台首页和前台首页 Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities(); boolean isAdmin = authorities.contains(new SimpleGrantedAuthority("ROLE_admin")); if(isAdmin){ httpServletResponse.sendRedirect("/admin"); }else { httpServletResponse.sendRedirect("/"); } } } }) // 用户登录失败处理 .failureHandler(new AuthenticationFailureHandler() { @Override public void onAuthenticationFailure(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { // 登录失败后,取出原始页面url并追加在重定向路径上 String url = httpServletRequest.getParameter("url"); httpServletResponse.sendRedirect("/login?error&url="+url); } }); // 3、设置用户登录后cookie有效期,默认值 http.rememberMe().alwaysRemember(true).tokenValiditySeconds(COOKIE_VALIDITY); // 4、自定义用户退出控制 http.logout().logoutUrl("/logout").logoutSuccessUrl("/"); // 5、针对访问无权限页面出现的403页面进行定制处理 http.exceptionHandling().accessDeniedHandler(new AccessDeniedHandler() { @Override public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException { // 如果是权限访问异常,则进行拦截到指定错误页面 RequestDispatcher dispatcher = httpServletRequest.getRequestDispatcher("/errorPage/comm/error_403"); dispatcher.forward(httpServletRequest, httpServletResponse); } }); //定制Remember-me记住我功能 http.rememberMe() .rememberMeParameter("rememberme") .tokenValiditySeconds(15) .tokenRepository(tokenRepository()); } // //自定义用户登录控制 @Bean public JdbcTokenRepositoryImpl tokenRepository() { JdbcTokenRepositoryImpl jr = new JdbcTokenRepositoryImpl(); jr.setDataSource(dataSource); return jr; } }