SpringSecurity5 (2) ——自定义登录页面

一、自定义登录页面

在实际项目开发中,根据需求设计业务系统的登录界面,不会使用security提供的默认登录页面,本文使用SpringBoot集成thymeleaf开发前端页面。

(一)开发登录页面

在resources目录下新建目录templates,存放模板文件,按照实际需求开发login.html,登录页面的用户名和密码的登录框name需要使用usernamepassword,如果需要改动,需要修改配置类。

<div><label> 用户名 : <input type="text" name="username"/> </label></div>
<div><label> 密码: <input type="password" name="password"/> </label></div>

(二)引入依赖

引入thymeleaf模板引擎依赖

    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
   </dependency>

(三)开发Controller

新建一个LoginController,跳转到login.html页面

@Controller
public class LoginController {
    @GetMapping("/login")
    public  String  skipLogin(){
        return "login";
    }

}

(四)修改配置类

在Java配置文件中修改以下方法,新增login()配置和defaultSuccessUrl()配置

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/hello/admin").hasRole("ROOT")
                .antMatchers("/hello").hasRole("USER").anyRequest().permitAll()
                .and()
                .csrf().disable().
                formLogin().loginPage("/login")  //自定义登录页面跳转
                .defaultSuccessUrl("/hello")//登录成功后跳转
                .and().httpBasic().disable()
                .sessionManagement().disable()
                .cors()
                .and()
                .logout();
    }

/***
defaultSuccessUrl 就是说,它会默认跳转到 Referer 来源页面,如果 Referer 为空,没有来源页,则跳转到默认设置的页面。如果有Referer则跳转到referer页面

successForwardUrl 表示不管你是从哪里来的,登录后一律跳转到 successForwardUrl 指定的地址。例如 successForwardUrl 指定的地址为 /index ,
**/

二、自定义登录成功、失败及退出逻辑

未登录时,我们访问后台接口服务/hello或者/hello/admin时,security会重定向到登录页面,当我们登录成功后,页面会重定向到登录前访问的url,可以查看上面defaultSuccessUrl和successForwardUrl的区别。

目前很多系统使用前后端分离方案,登录成功后,前端要求返回JSON字符串并把相应的信息存储到localStorage中,后续直接从取本地取出使用。

(一)开发登录成功逻辑

实现AuthenticationSuccessHandler接口,重写onAuthenticationSuccess方法,登录成功后不再重定向到/hello接口,直接往前台返回相应JSON字符串

@Component
public class AuthSuccessHandler implements AuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
            throws IOException, ServletException {
            //处理登录成功逻辑
        response.setHeader("Content-Type", "application/json;charset=utf-8");
        String jsonStr = "{username:\"张三\",token:\"avasdaeawaweqwe123123asdad1231dasdasd\"}";
                    response.getWriter().print(jsonStr);
                    response.getWriter().flush();
    }
}

登录成功后如下图所示

image-20200701170057728

(二)开发登录失败逻辑

实现AuthenticationFailureHandler接口,重写onAuthenticationFailure方法,认证失败不在返回到登录页面(/login?error)直接往前台返回相应JSON字符串

@Component
public class AuthFailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
            throws IOException, ServletException {
        //处理认证失败逻辑
        response.setHeader("Content-Type", "application/json;charset=utf-8");
        String jsonStr = "{code:\"400\",message:\"认证失败\"}";
        response.getWriter().print(jsonStr);
        response.getWriter().flush();
    }
}

(三)开发退出逻辑

@Component
public class AuthLogoutHandler implements LogoutHandler {
    @Override
    public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
    {
        /**
        	根据实际需求编写实际代码,可以是删除缓存中用户信息返回登录页面,或者是重定向到其他页面等
        	等,在此为了简便,后台打印一句话,向浏览器输出字符串。
        **/
        
        UserDetails user = (UserDetails) authentication.getPrincipal();
        System.out.println("删除用户信息"+user.getUsername());
        response.setHeader("Content-Type", "application/json;charset=utf-8");
        try {
            response.getWriter().print("缓存中用户信息已删除");
            response.getWriter().flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

(四)修改配置类

注入上面登录成功及失败的逻辑类

@Autowired
private AuthSuccessHandler  authSuccessHandler;

@Autowired
private AuthFailureHandler  authFailureHandler;

@Autowired
private AuthLogoutHandler authLogoutHandler;

增加successHandlerfailureHandler配置

   @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/hello/admin").hasRole("ROOT")
                .antMatchers("/hello").hasRole("USER").anyRequest().permitAll()
                .and()
                .csrf().disable().
                formLogin().loginPage("/login")  //自定义登录页面跳转
                .defaultSuccessUrl("/hello")
                .successForwardUrl("/hello/admin")//登录成功后跳转
                .successHandler(authSuccessHandler)
                .failureHandler(authFailureHandler)
                .and().httpBasic().disable()
                .sessionManagement().disable()
                .cors()
                .and() //退出的路径及退出后的逻辑操作
                .logout().logoutUrl("/logout").addLogoutHandler(authLogoutHandler);
    }

(五)验证效果

登录成功后效果:

登录失败后效果:

退出效果:
因没有开发退出按钮,从登录页面登录成功后,在浏览器上访问/logout接口,看下退出效果,已经在页面上显示

posted @ 2020-07-03 08:23  山那边风景  阅读(2350)  评论(0编辑  收藏  举报