<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.jpasecurity</groupId>
    <artifactId>SpringBootJpaSecurity</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <!-- 声明项目配置依赖编码格式为 utf-8 -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <fastjson.version>1.2.24</fastjson.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 添加MySQL依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
            <version>8.0.13</version><!--$NO-MVN-MAN-VER$ -->
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--devtools热部署 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
            <scope>true</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
server.servlet.context-path=/ch7_1
spring.datasource.url=jdbc:mysql://localhost:3306/springbootjpa?serverTimezone=UTC&autoReconnect=true
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.database=MYSQL
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jackson.serialization.indent-output=true
spring.thymeleaf.cache=false
logging.level.org.springframework.security=trace
package com.ch.ch7_1.entity;

import java.io.Serializable;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@Entity
@Table(name = "authority")
@JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler", "fieldHandler" })
public class Authority {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    @Column(nullable = false)
    private String name;
    @ManyToMany(mappedBy = "authorityList")
    @JsonIgnore
    private List<MyUser> userList;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<MyUser> getUserList() {
        return userList;
    }

    public void setUserList(List<MyUser> userList) {
        this.userList = userList;
    }
}
package com.ch.ch7_1.entity;

import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@Entity
@Table(name = "user")
@JsonIgnoreProperties(value = { "hibernateLazyInitializer","handler","fieldHandler" })
public class MyUser implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String username;
    private String password;
    // 这里不能是懒加载lazy,否则在MyUserSecurityService的loadUserByUsername方法中获得不到权限
    @ManyToMany(cascade = { CascadeType.REFRESH }, fetch = FetchType.EAGER)
    @JoinTable(name = "user_authority", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "authority_id"))
    private List<Authority> authorityList;

    // repassword不映射到数据表
    @Transient
    private String repassword;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public List<Authority> getAuthorityList() {
        return authorityList;
    }

    public void setAuthorityList(List<Authority> authorityList) {
        this.authorityList = authorityList;
    }

    public String getRepassword() {
        return repassword;
    }

    public void setRepassword(String repassword) {
        this.repassword = repassword;
    }
}
package com.ch.ch7_1.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import com.ch.ch7_1.entity.MyUser;

public interface MyUserRepository extends JpaRepository<MyUser, Integer> {
    // 根据用户名查询用户,方法名命名符合Spring Data JPA规范
    MyUser findByUsername(String username);
}
package com.ch.ch7_1.service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.ui.Model;
import com.ch.ch7_1.entity.MyUser;

public interface UserService {
    public String register(MyUser userDomain);

    public String loginSuccess(Model model);

    public String main(Model model);

    public String deniedAccess(Model model);

    public String logout(HttpServletRequest request, HttpServletResponse response);
}
package com.ch.ch7_1.service;

import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import com.ch.ch7_1.entity.Authority;
import com.ch.ch7_1.entity.MyUser;
import com.ch.ch7_1.repository.MyUserRepository;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private MyUserRepository myUserRepository;

    /**
     * 实现注册
     */
    @Override
    public String register(MyUser userDomain) {
        String username = userDomain.getUsername();
        List<Authority> authorityList = new ArrayList<Authority>();
        // 管理员权限
        if ("admin".equals(username)) {
            Authority a1 = new Authority();
            Authority a2 = new Authority();
            a1.setId(1);
            a1.setName("ROLE_ADMIN");
            a2.setId(2);
            a2.setName("ROLE_DBA");
            authorityList.add(a1);
            authorityList.add(a2);
        } else {// 用户权限
            Authority a1 = new Authority();
            a1.setId(3);
            a1.setName("ROLE_USER");
            authorityList.add(a1);
        }
        userDomain.setAuthorityList(authorityList);
        // 加密密码
        String secret = new BCryptPasswordEncoder().encode(userDomain.getPassword());
        userDomain.setPassword(secret);
        MyUser mu = myUserRepository.save(userDomain);
        if (mu != null)// 注册成功
            return "/login";
        return "/register";// 注册失败
    }

    /**
     * 用户登录成功
     */
    @Override
    public String loginSuccess(Model model) {
        model.addAttribute("user", getUname());
        model.addAttribute("role", getAuthorities());
        return "/user/loginSuccess";
    }

    /**
     * 管理员登录成功
     */
    @Override
    public String main(Model model) {
        model.addAttribute("user", getUname());
        model.addAttribute("role", getAuthorities());
        return "/admin/main";
    }

    /**
     * 注销用户
     */
    @Override
    public String logout(HttpServletRequest request, HttpServletResponse response) {
        // 获得用户认证信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            // 注销
            new SecurityContextLogoutHandler().logout(request, response, authentication);
        }
        return "redirect:/login?logout";
    }

    /**
     * 没有权限拒绝访问
     */
    @Override
    public String deniedAccess(Model model) {
        model.addAttribute("user", getUname());
        model.addAttribute("role", getAuthorities());
        return "deniedAccess";
    }

    /**
     * 获得当前用户名称
     */
    private String getUname() {
        return SecurityContextHolder.getContext().getAuthentication().getName();
    }

    /**
     * 获得当前用户权限
     */
    private String getAuthorities() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        List<String> roles = new ArrayList<String>();
        for (GrantedAuthority ga : authentication.getAuthorities()) {
            roles.add(ga.getAuthority());
        }
        return roles.toString();
    }
}
package com.ch.ch7_1.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import com.ch.ch7_1.entity.MyUser;
import com.ch.ch7_1.service.UserService;

@Controller
public class TestSecurityController {
    @Autowired
    private UserService userService;

    @RequestMapping("/")
    public String index() {
        return "/index";
    }

    @RequestMapping("/toLogin")
    public String toLogin() {
        return "/login";
    }

    @RequestMapping("/toRegister")
    public String toRegister(@ModelAttribute("userDomain") MyUser userDomain) {
        return "/register";
    }

    @RequestMapping("/register")
    public String register(@ModelAttribute("userDomain") MyUser userDomain) {
        return userService.register(userDomain);
    }

    @RequestMapping("/login")
    public String login() {
        // 这里什么都不错,由Spring Security负责登录验证
        return "/login";
    }

    @RequestMapping("/user/loginSuccess")
    public String loginSuccess(Model model) {
        return userService.loginSuccess(model);
    }

    @RequestMapping("/admin/main")
    public String main(Model model) {
        return userService.main(model);
    }

    @RequestMapping("/logout")
    public String logout(HttpServletRequest request, HttpServletResponse response) {
        return userService.logout(request, response);
    }

    @RequestMapping("/deniedAccess")
    public String deniedAccess(Model model) {
        return userService.deniedAccess(model);
    }
}
package com.ch.ch7_1.security;

import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.ch.ch7_1.entity.Authority;
import com.ch.ch7_1.entity.MyUser;
import com.ch.ch7_1.repository.MyUserRepository;

/**
 * 获得对应的UserDetails,保存与认证相关的信息
 */
@Service
public class MyUserSecurityService implements UserDetailsService {
    @Autowired
    private MyUserRepository myUserRepository;

    /**
     * 通过重写loadUserByUsername方法查询对应的用户 UserDetails是Spring Security的一个核心接口
     * UserDetails定义了可以获取用户名、密码、权限等与认证相关信息的方法
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 根据用户名(页面接收的用户名)查询当前用户
        MyUser myUser = myUserRepository.findByUsername(username);
        if (myUser == null) {
            throw new UsernameNotFoundException("用户名不存在");
        }
        // GrantedAuthority代表赋予当前用户的权限(认证权限)
        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        // 获得当前用户权限集合
        List<Authority> roles = myUser.getAuthorityList();

        // 将当前用户的权限保存为用户的认证权限
        for (Authority authority : roles) {
            GrantedAuthority sg = new SimpleGrantedAuthority(authority.getName());
            authorities.add(sg);
        }
        // org.springframework.security.core.userdetails.User是Spring Security的内部实现,
        // 专门用于保存用户名、密码、权限等与认证相关的信息
        User su = new User(myUser.getUsername(), myUser.getPassword(), authorities);
        return su;
    }
}
package com.ch.ch7_1.security;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

@Component
/**
 * 用户授权、认证成功处理类
 */
public class MyAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
    // Spring Security的重定向策略
    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    /**
     * 重写handle方法,通过RedirectStrategy重定向到指定的URL
     */
    @Override
    protected void handle(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
            throws IOException, ServletException {
        // 根据当前认证用户的角色返回适当的URL
        String tagetURL = getTargetURL(authentication);
        // 重定向到指定的URL
        redirectStrategy.sendRedirect(request, response, tagetURL);
    }

    /**
     * 从Authentication对象中提取当前登录用户的角色,并根据其角色返回适当的URL
     */
    protected String getTargetURL(Authentication authentication) {
        String url = "";
        // 获得当前登录用户的权限(角色)集合
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        List<String> roles = new ArrayList<String>();
        // 将权限(角色)名称添加到List集合
        for (GrantedAuthority au : authorities) {
            roles.add(au.getAuthority());
        }
        // 判断不同角色的用户跳转到不同的URL
        // 这里的URL是控制器的请求匹配路径
        if (roles.contains("ROLE_USER")) {
            url = "/user/loginSuccess";
        } else if (roles.contains("ROLE_ADMIN")) {
            url = "/admin/main";
        } else {
            url = "/deniedAccess";
        }
        return url;
    }
}
package com.ch.ch7_1.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * 认证和授权处理类
 */
@Configuration
public class MySecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
    // 依赖注入通用的用户服务类
    @Autowired
    private MyUserSecurityService myUserSecurityService;
    // 依赖注入加密接口
    @Autowired
    private PasswordEncoder passwordEncoder;
    // 依赖注入用户认证接口
    @Autowired
    private AuthenticationProvider authenticationProvider;
    // 依赖注入认证处理成功类,验证用户成功后处理不同用户跳转到不同的页面
    @Autowired
    private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;

    /**
     * BCryptPasswordEncoder是PasswordEncoder的接口实现 实现加密功能
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * DaoAuthenticationProvider是AuthenticationProvider的实现
     */
    @Bean
    public AuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider provide = new DaoAuthenticationProvider();
        // 不隐藏用户未找到异常
        provide.setHideUserNotFoundExceptions(false);
        // 设置自定义认证方式,用户登录认证
        provide.setUserDetailsService(myUserSecurityService);
        // 设置密码加密程序认证
        provide.setPasswordEncoder(passwordEncoder);
        return provide;
    }

    /**
     * 用户认证
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        System.out.println("configure(AuthenticationManagerBuilder auth) ");
        // 设置认证方式
        auth.authenticationProvider(authenticationProvider);
    }

    /**
     * 请求授权 用户授权操作
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        System.out.println("configure(HttpSecurity http)");
        http.authorizeRequests()
                // 首页、登录、注册页面、登录注册功能、以及静态资源过滤掉,即可任意访问
                .antMatchers("/toLogin", "/toRegister", "/", "/login", "/register", "/css/**", "/fonts/**", "/js/**")
                .permitAll()
                // 这里默认追加ROLE_,/user/**是控制器的请求匹配路径
                .antMatchers("/user/**").hasRole("USER").antMatchers("/admin/**").hasAnyRole("ADMIN", "DBA")
                // 其他所有请求登录后才能访问
                .anyRequest().authenticated().and()
                // 将输入的用户名与密码和授权的进行比较
                .formLogin().loginPage("/login").successHandler(myAuthenticationSuccessHandler)
                .usernameParameter("username").passwordParameter("password")
                // 登录失败
                .failureUrl("/login?error").and()
                // 注销行为可任意访问
                .logout().permitAll().and()
                // 指定异常处理页面
                .exceptionHandling().accessDeniedPage("/deniedAccess");
    }
}
package com.ch.ch7_1;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Ch71Application {
    public static void main(String[] args) {
        SpringApplication.run(Ch71Application.class, args);
    }
}
启动项目,后台打印下面截图这个提示,就表示自定义的用户认证和用户授权工作已经生效。

 

 

http://localhost:8080/ch7_1/login

 

 

 

 

 

 

 

 

 

 

 

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}" />
</head>
<body>
    <div class="panel panel-primary">
        <div class="panel-heading">
            <h3 class="panel-title">拒绝访问页面</h3>
        </div>
    </div>
    <div class="container">
        <div>
            <h3><span th:text="${user}"></span>您没有权限访问该页面!您的权限是您的权限是<span th:text="${role}"></span></h3><br><br>
            <a th:href="@{/logout}">安全退出</a>
        </div>
    </div>
</body>
</html>
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
<link rel="stylesheet" th:href="@{css/bootstrap.min.css}" />
</head>
<body>
    <div class="panel panel-primary">
        <div class="panel-heading">
            <h3 class="panel-title">Spring Security测试首页</h3>
        </div>
    </div>
    <div class="container">
        <div>
            <a th:href="@{/toLogin}">去登录</a><br><br>
            <a th:href="@{/toRegister}">去注册</a>
        </div>
    </div>
</body>
</html>
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
<link rel="stylesheet" th:href="@{css/bootstrap.min.css}" />
<script type="text/javascript" th:src="@{js/jquery.min.js}"></script>
<script type="text/javascript">
    $(function(){
        $("#loginBtn").click(function(){
            var username = $("#username");
            var password = $("#password");
            var msg = "";
            if(username.val() == ""){
                msg = "用户名不能为空!";
                username.focus();
            }else if(password.val() == ""){
                msg = "密码不能为空!";
                password.focus();
            }
            if(msg != ""){
                alert(msg);
                return false;
            }
            $("#myform").submit();
        });
    });
</script>
<body>
    <div class="container">
    <div class="bg-primary"  style="width:100%; height: 70px;padding-top: 10px;">
           <h2 align="center">用户登录</h2>
       </div>
        <br>
        <br>
        <form th:action="@{/login}"  id="myform" method="post"  class="form-horizontal" role="form" >
            <!-- 用户名或密码错误 -->
            <div th:if="${param.error != null}">
                <div class="alert alert-danger">
                    <p><font color="red">用户名或密码错误!</font></p>
                </div>
            </div>
            <!-- 注销 -->
            <div th:if="${param.logout != null}">
                <div class="alert alert-success">
                    <p><font color="red">用户已注销成功!</font></p>
                </div>
            </div>
            <div class="form-group has-success">
                <label class="col-sm-2 col-md-2 control-label">用户名</label>
                <div class="col-sm-4 col-md-4">
                    <input type="text" class="form-control"
                     placeholder="请输入您的用户名"
                    name="username" id="username"/>
                </div>
            </div>
            <div class="form-group has-success">
                  <label class="col-sm-2 col-md-2 control-label">密码</label>
                  <div class="col-sm-4 col-md-4">
                          <input type="password" class="form-control"
                     placeholder="请输入您的密码" name="password" id="password"/>
                  </div>
             </div> 
            <div class="form-group">
                <div class="col-sm-offset-2 col-sm-10">
                    <button type="button" id="loginBtn" class="btn btn-success" >登录</button>
                    <button type="reset" class="btn btn-primary" >重置</button>
                </div>
            </div>
        </form>
    </div>
</body>
</html>
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>注册页面</title>
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}" />
<script th:src="@{/js/jquery.min.js}"></script>
<script type="text/javascript" th:inline="javascript">
    function checkBpwd(){
        if($("#username").val() == ""){
            alert("用户名必须输入!");
            $("#username").focus();
            return false;
        }else if($("#password").val() == ""){
            alert("密码必须输入!");
            $("#password").focus();
            return false;
        }else if($("#password").val() != $("#repassword").val()){
            alert("两次密码不一致!");
            $("#password").focus();
            return false;
        }else{
            document.myform.submit();
        }
    }
</script>
<body>
    <div class="container">
          <div class="bg-primary"  style="width:100%; height: 70px;padding-top: 10px;">
           <h2 align="center">用户注册</h2>
       </div>
        <br>
        <br>
        <form th:action="@{/register}" name="myform" method="post" th:object="${userDomain}"  class="form-horizontal" role="form" >
            <div class="form-group has-success">
                <label class="col-sm-2 col-md-2 control-label">用户名</label>
                <div class="col-sm-4 col-md-4">
                    <input type="text" class="form-control"
                     placeholder="请输入您的用户名"
                    th:field="*{username}"/>
                </div>
            </div>
    
            <div class="form-group has-success">
                  <label class="col-sm-2 col-md-2 control-label">密码</label>
                  <div class="col-sm-4 col-md-4">
                          <input type="password" class="form-control"
                     placeholder="请输入您的密码" th:field="*{password}" />
                  </div>
             </div>
    
            <div class="form-group has-success">
                  <label class="col-sm-2 col-md-2 control-label">确认密码</label>
                  <div class="col-sm-4 col-md-4">
                          <input type="password" class="form-control"
                     placeholder="请输入您的密码" th:field="*{repassword}"/>
                  </div>
             </div>
    
            <div class="form-group">
                <div class="col-sm-offset-2 col-sm-10">
                    <button type="button" onclick="checkBpwd()" class="btn btn-success" >注册</button>
                    <button type="reset" class="btn btn-primary" >重置</button>
                </div>
            </div>
        </form>
    </div>
</body>
</html>
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}" />
</head>
<body>
    <div class="panel panel-primary">
        <div class="panel-heading">
            <h3 class="panel-title">登录成功页面</h3>
        </div>
    </div>
    <div class="container">
        <div>
            <h3>欢迎<span th:text="${user}"></span>登录成功!您的权限是<span th:text="${role}"></span></h3><br><br>
            <a th:href="@{/admin/main}">去访问管理员页面</a><br><br>
            <a th:href="@{/logout}">安全退出</a>
        </div>
    </div>
</body>
</html>
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}" />
</head>
<body>
    <div class="panel panel-primary">
        <div class="panel-heading">
            <h3 class="panel-title">管理员页面</h3>
        </div>
    </div>
    <div class="container">
        <div>
            <h3>欢迎<span th:text="${user}"></span>访问管理员页面!您的权限是<span th:text="${role}"></span></h3><br><br>
            <a th:href="@{/user/loginSuccess}">去访问用户登录成功页面</a><br><br>
            <a th:href="@{/logout}">安全退出</a>
        </div>
    </div>
</body>
</html>