Fms-Java版开发实录:04 编写自定义登录页面

Fms-Java版开发实录:04 编写自定义登录页面

Thymeleaf是个好东西

自定义登录界面采用了BootStrap官网例子,当然还不能直接使用,必须先修改页面的内容,再修改对应的控制器以及Spring Security的配置。

引入Thymeleaf和修改页面

把源码包下载回来,将其中的index.html复制到新创建的resources\template\account目录中,重新命名为login.html,然后删除head标签中的一些作者和其他信息,然后要开始使用Thymeleaf了。

首先是在html标签中引入Thymeleaf的命名空间:

<html lang="zh" xmlns:th="http://www.thymeleaf.org">

之后将下边这行:

    <link href="../assets/dist/css/bootstrap.min.css" rel="stylesheet">

修改为:

    <link href="/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" rel="stylesheet">

这里尽量遵循Thymeleaf的本意,就是不破坏原有页面结构。
下边那一行引入了signin.css,我直接把signin.css的内容复制到了head标签里,这样就只用这一个文件就可以了。

修改页面内容

首先是图标,需要显示原始的比例,所以去掉高和宽,改成公司的图标:

<img class="mb-4" src="/img/sinochem.png" th:src="@{/img/sinochem.png}" alt="中化集团" >

然后继续将英文Please sign in修改成“请登录”,之后修改两个input框的内容,由于Spring Security默认的表单键是username和password,修改如下:

<div class="form-floating">
    <input type="text" class="form-control" id="floatingInput" placeholder="用户名" name="username">
    <label for="floatingInput">用户名</label>
</div>
<div class="form-floating">
    <input type="password" name="password" class="form-control" id="floatingPassword" placeholder="密码">
    <label for="floatingPassword">密码</label>
</div>

接下来的复选框Remember Me我不需要,就把这一部分删除。之后再修改好后边的登录按钮和版权信息。

修改表单POST地址

这是一个非常重要的环节,刚才我们没有修改form表单,form表单需要将数据POSTSpring Security用于验证的地址,为了URL的统一规范,我打算用户相关的超链接都用/account/开头,所以准备把POST地址设置为/account/auth,修改如下:

<form action="/account/auth" th:action="@{/account/auth}" method="post">

配置控制器

由于Spring Security可以指定自定义登录界面的URL,我打算设置为/account/login,所以要为这个地址编写一个控制器。打算把所有/account/开头的控制器都集中到一个类中,在cc.conyli.fms下创建controller包,然后创建AccountController类:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/account")
public class AccountController {
    
    @RequestMapping("/login")
    public String login() {
        return "/account/index";
    }
}

修改Spring Security配置

既然现在有了对应/account/login路径的控制器,并且返回我们自己的页面,那么想到可以修改Spring Security配置如下:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .anyRequest().authenticated()
            .and()
    .formLogin().loginPage("/account/login").permitAll();
}

就是添加了loginPage("/account/login"),然后启动项目,随便访问路径,可以看到显示出了自定义的页面,然而问题是:没有样式

解决不显示样式的问题

页面没有样式的原因是,除了/account/login这个路径之外,所有的路径都被Spring Security保护起来,包括静态文件的路径,很显然,需要让Spring Security放开这几个路径,于是继续修改配置:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/css/**","/img/**","/js/**","/webfonts/**").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin().loginPage("/account/login").permitAll();
}

此时再刷新,就会发现样式显示正常了。

修改验证地址

目前输入用户名和密码发现没有用,这是因为表单里设置了POST地址是/account/auth,但是Spring Security并没有设置这个POST地址接受表单提交,需要继续修改:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/css/**","/img/**","/js/**","/webfonts/**").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin().loginPage("/account/login").loginProcessingUrl("/account/auth").permitAll();
}

加了loginProcessingUrl("/account/auth")Spring Security的过滤器就会在这个地址等着接收包含usermanepassword的表单,然后返回登录是否成功的响应。

再重新运行项目,输入用户名和密码后,如果登录成功就会跳转到刚才想访问的路径,如果登录失败,则会返回http://localhost:8080/account/login?error这样一个地址,既然登录失败,需要给用户一个提示,于是我们还需要对页面做一个处理,来提示登录失败。

修改控制器检查error参数

控制器需要检查URL参数error是否存在,于是这里可以用到Spring@RequestParam(required = false)来接受参数

@RequestMapping("/login")
public String login(@RequestParam(required = false, name = "error") String failed, Model model) {
    //URL中的error参数存在,则在model中放入一个"failed"键,在页面中通过if来判断。
    if (failed != null) {
        model.addAttribute("failed", "用户名或密码错误,或用户未激活,请联系管理员");
    }
    return "/account/login";
}

使用th:if在页面中进行判断

在页面中form标签的h3标题之后,加上一个alert组件:

<div th:if="${failed} != null" class="alert alert-danger" role="alert">
    用户名或密码错误,或用户未激活,请联系管理员。
</div>

当出现错误,控制器在模型中放入failed之后,页面中就通过判断展示alert组件。这样就写好了自定义的登录页面。

LICENSED UNDER CC BY-NC-SA 4.0
Comment