基于springboot+bootstrap+mysql+redis搭建一套完整的权限架构整合springSecurity
Posted ljljlj1993
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于springboot+bootstrap+mysql+redis搭建一套完整的权限架构整合springSecurity相关的知识,希望对你有一定的参考价值。
1、创建数据库
注意:mysql默认字符集为utf8,默认排序规则为utf8_general_ci。一般我们也会选择字符集为utf-8
MySQL在5.5.3之后增加了这个utf8mb4的编码,utf8mb4完全向下兼容utf8,为了节省空间,一般情况下使用utf8也就够了,我这边没有utf8。所以选择了utf8mb4 。
2、建表
若需要整合我们的springSecurity,一种是直接使用springSecurity自带的权限架构,另外一种是使用我们自己设计的数据架构,本文所阐述的就是使用自己设计的RBAC权限架构,因此我们要事先设计好用户权限架构的PDM如下图所示,并创建我们的数据库:数据库名:hyll_springboot,以及我们的三张表:user、user_role、user_associate_role:
接着打开我们的工程新建如下工程的目录:
接着在我们的sys包底下新建entity和dao这两个包:
同时打开我们的pom.xml引入该工程所需要的所有依赖,接着我们的IDEA会弹出一个框,我们点击import就自动会去maven给我们下载依赖,若你有自己的私有maven则将其指向自己的私有maven,若这边有缺少不懂的直接去我的第一章的github上的源代码中自己去copy下来:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<mysql.version>5.1.41</mysql.version>
<guava.version>18.0</guava.version>
<org.mapstruct.version>1.1.0.Final</org.mapstruct.version>
</properties>
<dependencies>
<!-- 集成Druid数据库连接池和监控 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.3</version>
</dependency>
<!-- 引入mybatis的支持 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<!-- 引入mapstruct的支持 -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>$org.mapstruct.version</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>$org.mapstruct.version</version>
</dependency>
<!-- Java EE 6 规范 JSR 330 -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- 引入json的依赖 classifier必须要加这个是json的jdk的依赖-->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
<!-- 开启spring-websocket的支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- 开启spring-security的支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- 开启thymeleaf的spring-security的支持 -->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
<!-- 表示对thymeleaf模板不再是用默认的html5标准来做严格限制 -->
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
<version>1.9.22</version>
</dependency>
<!-- 添加对spring-redis的支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
<version>1.3.8.RELEASE</version>
</dependency>
<!-- 添加对spring-cache的支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
<!-- 添加对spring-data-rest的支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<!-- 添加对spring-jpa的支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>$mysql.version</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>$guava.version</version>
</dependency>
<!-- 添加对thymeleaf的支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- 添加对websocket的支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>1.3.5.RELEASE</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional><!-- optional=true,依赖不会传递,该项目依赖devtools;之后依赖myboot项目的项目如果想要使用devtools,需要重新引入 -->
</dependency>
<dependency>
<groupId>com.xiaoleilu</groupId>
<artifactId>hutool-all</artifactId>
<version>3.0.9</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>com.vaadin.external.google</groupId>
<artifactId>android-json</artifactId>
<version>0.0.20131108.vaadin1</version>
</dependency>
</dependencies>
同时在我们的entity包底下新建我们刚刚的三个实体:
UserRole 的代码部分
package com.example.demo.sys.entity;
/**
* @author lj
* @version 1.0
* @date 2023/1/314:18
* Description:com.example.demo.sys.entity
*/
public class UserRole
private long id;
private String name;
private String roleName;
public long getId()
return id;
public void setId(long id)
this.id = id;
public String getName()
return name;
public void setName(String name)
this.name = name;
public String getRoleName()
return roleName;
public void setRoleName(String roleName)
this.roleName = roleName;
User 代码部分
package com.example.demo.sys.entity;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
/**
* @author lj
* @version 1.0
* @date 2023/1/310:01
* Description:com.example.demo.sys.entity
*/
public class User implements UserDetails
private int id;
private String login;
private String password;
private String userName;
private String address;
private String job;
private long groupId;
private Date birthDate;
private String city;
private String district;
private String province;
private String streetAddress;
private String state;
private String type;
private Date lastLoginDate;
// 用户角色信息
private List<UserRole> roles;
// 权限集合数据
private String roleArray;
public int getId()
return id;
public void setId(int id)
this.id = id;
public String getLogin()
return login;
public void setLogin(String login)
this.login = login;
public void setPassword(String password)
this.password = password;
public String getUserName()
return userName;
public void setUserName(String userName)
this.userName = userName;
public String getAddress()
return address;
public void setAddress(String address)
this.address = address;
public String getJob()
return job;
public void setJob(String job)
this.job = job;
public long getGroupId()
return groupId;
public void setGroupId(long groupId)
this.groupId = groupId;
public Date getBirthDate()
return birthDate;
public void setBirthDate(Date birthDate)
this.birthDate = birthDate;
public String getCity()
return city;
public void setCity(String city)
this.city = city;
public String getDistrict()
return district;
public void setDistrict(String district)
this.district = district;
public String getProvince()
return province;
public void setProvince(String province)
this.province = province;
public String getStreetAddress()
return streetAddress;
public void setStreetAddress(String streetAddress)
this.streetAddress = streetAddress;
public String getState()
return state;
public void setState(String state)
this.state = state;
public String getType()
return type;
public void setType(String type)
this.type = type;
public Date getLastLoginDate()
return lastLoginDate;
public void setLastLoginDate(Date lastLoginDate)
this.lastLoginDate = lastLoginDate;
public List<UserRole> getRoles()
return roles;
public void setRoles(List<UserRole> roles)
this.roles = roles;
public String getRoleArray()
return roleArray;
public void setRoleArray(String roleArray)
this.roleArray = roleArray;
@Override
public Collection<? extends GrantedAuthority> getAuthorities()
List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
if (this.getRoles() != null)
List<UserRole> roles = this.getRoles();
for (UserRole role : roles)
if (role.getName() != null)
auths.add(new SimpleGrantedAuthority(role.getName()));
return auths;
@Override
public String getPassword()
return null;
@Override
public String getUsername()
return null;
@Override
public boolean isAccountNonExpired()
return false;
@Override
public boolean isAccountNonLocked()
return false;
@Override
public boolean isCredentialsNonExpired()
return false;
@Override
public boolean isEnabled()
return false;
/**
* 功能描述:组装角色数据集合
*
* @param roleArray
*/
public void packagingRoles(String roleArray)
List<UserRole> roles = new ArrayList<UserRole>();
if (roleArray != null)
UserRole userRole = null;
for (String roleId : roleArray.split(","))
if (!roleId.isEmpty())
userRole = new UserRole();
userRole.setId(Long.parseLong(roleId));
roles.add(userRole);
this.setRoles(roles);
UserAssociateRole 代码部分
package com.example.demo.sys.entity;
/**
* @author lj
* @version 1.0
* @date 2023/1/314:26
* Description:com.example.demo.sys.entity
*/
public class UserAssociateRole
private int userId;
private long roleId;
public UserAssociateRole()
super();
public int getUserId()
return userId;
public void setUserId(int userId)
this.userId = userId;
public long getRoleId()
return roleId;
public void setRoleId(long roleId)
this.roleId = roleId;
接着我们在dao包里面创建以下的接口:
package com.example.demo.sys.dao;
import com.example.demo.sys.entity.User;
/**
* @author lj
* @version 1.0
* @date 2023/1/314:54
* Description:com.example.demo.sys.dao
*/
public interface UserDao
/**
* 功能描述:根据账户获取用户信息
*
* @param user
* @return com.example.demo.sys.entity.User
* @author: LJ
* @date: 2023/1/3
*/
User findByLogin(String user);
接着我们引入我们的mybatis配置以及我们的security和快速切换环境配置,
首先在我们的application.properties底下增加以下配置:
spring.profiles.active=dev
#配置放行的目录和方法
security.ignored=/api/*,/css/*,/js/*,/images/*,/fonts/*,/font-awesome/*
#表示对thymeleaf模板不再是用默认的HTML5标准来做严格限制
spring.thymeleaf.mode = LEGACYHTML5
#配置mybatis的扫描的包的文件的入口
mybatis.config-locations=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
同时在我们的resources目录底下创建一个目录mybatis并在该目录底下创建一个文件mybatis-config.xml和mapper目录如下所示:
mybatis-config.xml代码如下所示
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias alias="Integer" type="java.lang.Integer" />
<typeAlias alias="Long" type="java.lang.Long" />
<typeAlias alias="HashMap" type="java.util.HashMap" />
<typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap" />
<typeAlias alias="ArrayList" type="java.util.ArrayList" />
<typeAlias alias="LinkedList" type="java.util.LinkedList" />
</typeAliases>
</configuration>
同时在我们的resource目录底下创建我们的application-dev.properties文件信息如下:
server.port = 8080
#数据库连接配置
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/hyll_springboot?characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=111111
接着我们在resource/mapper目录底下创建一个mybatis_user.xml内容如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias alias="Integer" type="java.lang.Integer" />
<typeAlias alias="Long" type="java.lang.Long" />
<typeAlias alias="HashMap" type="java.util.HashMap" />
<typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap" />
<typeAlias alias="ArrayList" type="java.util.ArrayList" />
<typeAlias alias="LinkedList" type="java.util.LinkedList" />
</typeAliases>
</configuration>
同时在我们的resource目录底下创建我们的application-dev.properties文件信息如下
server.port = 8080
#数据库连接配置
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/hyll_springboot?characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=111111
接着我们在resource/mapper目录底下创建一个mybatis_user.xml内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.sys.dao.UserDao">
<!-- 包含角色信息的map -->
<resultMap type="com.example.demo.sys.entity.User" id="UserLoginMap">
<id property="id" column="id"/>
<result property="login" column="login"/>
<result property="password" column="password"/>
<result property="userName" column="user_name"/>
<result property="address" column="address"/>
<result property="job" column="job"/>
<result property="groupId" column="group_id"/>
<result property="birthDate" column="birth_date"/>
<result property="city" column="city"/>
<result property="district" column="district"/>
<result property="province" column="province"/>
<result property="streetAddress" column="street_address"/>
<result property="state" column="state"/>
<result property="type" column="type"/>
<result property="lastLoginDate" column="last_login_date"/>
<collection property="roles" ofType="com.example.demo.sys.entity.UserRole" javaType="java.util.ArrayList">
<result column="user_role_id" property="id" jdbcType="VARCHAR" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="role_name" property="roleName" jdbcType="VARCHAR" />
</collection>
</resultMap>
<!-- 根据账号来获取用户信息 -->
<select id="findByLogin" parameterType="java.lang.String" resultMap="UserLoginMap">
select u.*,ur.id as user_role_id,ur.name,ur.role_name from user u inner join user_associate_role uar on u.id = uar.user_id inner join user_role ur on uar.role_id = ur.id where u.login = #login
</select>
</mapper>
接着开始我们的springsecurity的配置,找到我们的config包在该包底下我们创建一个security和mybatis包如下所示
接着在我们的security增加以下三个类分别是(CustomPasswordEncoder:密码加密类;CustomUserService:登陆逻辑重写类;WebSecurityConfig:security实现配置类):
注意maven的版本,如果版本高的话,就没有Md5PasswordEncoder的依赖
package com.example.demo.common.config.security;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
/**
* 功能描述:spring-security登陆的密码进行MD5加密传到数据库
*
* @author: LJ
* @date: 2023/1/3
* @return
*/
public class CustomPasswordEncoder implements PasswordEncoder
@Override
public String encode(CharSequence rawPassword)
Md5PasswordEncoder encoder = new Md5PasswordEncoder();
return encoder.encodePassword(rawPassword.toString(), "hyll");
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword)
Md5PasswordEncoder encoder = new Md5PasswordEncoder();
return encoder.isPasswordValid(encodedPassword, rawPassword.toString(), "hyll");
注意,你得密码是经过md5加密得,所以比如我得密码是1,那么加密后得a2098ac42fe033111a1f678b8d621899,这个填入到数据库中对应user表得密码中,你可以根据自己的密码进行加密,加密后的结果放到数据库中
public static void main(String[] args)
Md5PasswordEncoder encoder = new Md5PasswordEncoder();
System.out.println(encoder.encodePassword("1", "hyll"));
System.out.println( encoder.isPasswordValid("a2098ac42fe033111a1f678b8d621899","1", "hyll"));
package com.example.demo.common.config.security;
import com.example.demo.sys.dao.UserDao;
import com.example.demo.sys.entity.User;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import javax.annotation.Resource;
/**
* @author lj
* @version 1.0
* @date 2023/1/510:51
* Description:com.example.demo.common.config.security
*/
public class CustomUserService implements UserDetailsService
@Resource
private UserDao userDao;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException
User user = userDao.findByLogin(s);
if (user == null)
throw new UsernameNotFoundException("用户名不存在");
// 自定义错误的文章说明的地址:http://blog.csdn.net/z69183787/article/details/21190639?locationNum=1&fps=1
if (user.getState().equalsIgnoreCase("0"))
throw new LockedException("用户账号被冻结,无法登陆请联系管理员!");
return user;
package com.example.demo.common.config.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* @author lj
* @version 1.0
* @date 2023/1/513:34
* 实现Security的配置
*/
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
//当我们想要开启spring方法级安全时,只需要在任何 @Configuration实例上使用 @EnableGlobalMethodSecurity 注解就能达到此目的
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
@Bean
UserDetailsService customUserService()
return new CustomUserService();
@Bean
PasswordEncoder passwordEncoder()
return new CustomPasswordEncoder();
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
auth.userDetailsService(customUserService()).passwordEncoder(passwordEncoder());
@Override
protected AuthenticationManager authenticationManager() throws Exception
return super.authenticationManager();
/**
* 功能描述: csrf().disable()为了关闭跨域访问的限制,若不关闭则websocket无法与后台进行连接
*
* @param http
* @return void
* @author: LJ
* @date: 2023/1/5
*/
@Override
protected void configure(HttpSecurity http) throws Exception
http.headers().frameOptions().disable();
http.csrf().disable().authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/main")
.failureUrl("/login?error=true")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/login")
.permitAll();
接着我们在mybatis包底下新增MyBatisConfig 配置类如下所示 MapperScan扫描的是我们的dao接口的存放路径,因此此处大家一定要注意自己的dao包的路径是否正确,否则会导致调用dao方法出错】:
package com.example.demo.common.config.mybatis;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
/**
* @author lj
* @version 1.0
* @date 2023/1/2520:15
* Description:com.example.demo.common.config.mybatis
*/
@Configuration
@MapperScan("com.example.demo.*.dao")
public class MyBatisConfig
接着在我们的config目录底下创建我们的WebMvcConfig配置文件如下所示:
package com.example.demo.common.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* @author lj
* @version 1.0
* @date 2023/1/2520:21
* Description:com.example.demo.common.config
*/
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter
/**
* 重写方法描述:实现在url中输入相应的地址的时候直接跳转到某个地址
*
* @param registry
*/
@Override
public void addViewControllers(ViewControllerRegistry registry)
registry.addViewController("/login").setViewName("login");
registry.addViewController("/main").setViewName("main");
registry.addViewController("/error").setViewName("error");
到此处我们的整个基础工程已经构建完成,我们可以直接将该工程运行起来,访问http://127.0.0.1:8080/login,由于还没有引入bootstrap因此整个页面显得不叫的丑,后续将bootstrap引入那么你们就会发现我们的页面越来越漂亮,运行效果如下图所示:
基于springboot+bootstrap+mysql+redis搭建一套完整的权限架构引入bootstrap前端框架
https://blog.csdn.net/linzhefeng89/article/details/78752658
基于springboot+bootstrap+mysql+redis搭建一套完整的权限架构【六】【引入bootstrap前端框架】
bootstrap是目前最受欢迎的前端框架,bootstrap是基于HTML、CSS、JAVASCRIPT的,她界面美光、代码简介、开发灵活,因此深受开发者的喜爱,本文中用的bootstrap框架的版本是3.0以上的版本,若大家对bootstrap框架有兴趣可以直接到她的官方网站直接查阅相应的文档信息,官网地址:http://getbootstrap.com/。
由于bootstrap实际上我们在谷歌的时候会发现已经有大量的大神已经基于bootstrap给我们搭建好了各种各样的DEMO,因此我们完全没有必要自己去闭门造车,我们直接拿着前人写好的DEMO我们自己修改下就可以变成我们自己的东西,由于深入bootstrap的话那就是要一个专题来讲解了,此处主要讲解的是如何基于bootstrap来搭建一套完整的权限架构因此就不再此处深入的去讲解该框架,只要大家跑过一遍代码可以懂得如何使用就好了,若像更深入的去学习,那么大家去网上搜索下资料,上面有大量的资料供大家学习。
首先基于我们的第五章的工程我们将我们事先已经封装好的bootstrap脚本引入到我们现有的工程,大家若需要该快的代码,请大家直接在文章的末尾去github上自己去拿此块封装的代码,目录如下:
到此我们的bootstraop框架引入完成,那么基于bootstrap框架我们现在开始开发属于我们的第一个bootstrap页面登陆页,打开我们的templates文件在底下找到我们login.html页面,进行重新的编辑该页面代码如下:
-
-
<html xmlns:th="http://www.thymeleaf.org">
-
<head>
-
<meta content="text/html;charset=UTF-8"/>
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
-
<title>登录页面</title>
-
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"/>
-
<style type="text/css">
-
body {
-
padding-top: 50px;
-
}
-
.starter-template {
-
padding: 40px 15px;
-
text-align: center;
-
}
-
</style>
-
</head>
-
<body>
-
<!--/
-
<nav class="navbar navbar-inverse navbar-fixed-top">
-
<div class="container">
-
<div class="navbar-header">
-
<a class="navbar-brand" href="#">Spring Security演示</a>
-
</div>
-
<div id="navbar" class="collapse navbar-collapse">
-
<ul class="nav navbar-nav">
-
<li><a th:href="@{/}"> 首页 </a></li>
-
-
</ul>
-
</div>.nav-collapse
-
</div>
-
</nav>
-
-->
-
<div class="container">
-
-
<div class="starter-template">
-
<p th:if="${param.logout}" class="bg-warning">已成功注销</p><!-- 1 -->
-
<p th:if="${param.error}" th:text="${session.SPRING_SECURITY_LAST_EXCEPTION.message}==‘Bad credentials‘?‘账号/密码错误!‘:${session.SPRING_SECURITY_LAST_EXCEPTION.message}" class="bg-danger">
-
-
</p> <!-- 2 -->
-
<h2>使用账号密码登录</h2>
-
<form name="form" th:action="@{/login}" action="/login" method="POST"> <!-- 3 -->
-
<div class="form-group">
-
<label for="username">账号</label>
-
<input type="text" class="form-control" name="username" id="username" value="" placeholder="账号" />
-
</div>
-
<div class="form-group">
-
<label for="password">密码</label>
-
<input type="password" class="form-control" name="password" id="password" placeholder="密码" />
-
</div>
-
<input type="submit" id="login" value="Login" class="btn btn-primary" />
-
</form>
-
</div>
-
-
</div>
-
-
</body>
-
</html>
到此我们的登陆的首页已经完成了,接着我们再开发我们登陆成功以后的主页main.html,在我们编写我们的主页的时候,我们需要重新设计下我们的数据库,因此我们现有的表结构无法支撑起来我们的整个业务系统,因此我们重新设计了我们的数据库如下图:
接着我们直接生成我们的数据库执行脚本,并在我们的数据库中执行,同时使用我们上一章开发的工具我们来快速生成我们的代码,并根据我们的权限架构来修改我们的代码,以下是经过修改以后的代码的结构:
在我们的工程中有一些我们经常用到的CSS或者js 我们并不想每个页面都进行一次引用,因此我们新建一个全局的引用到我们的工程(在templates底下新建一个文件夹include同时创建includebase.html文件)中如下:
-
<html xmlns:th="http://www.thymeleaf.org">
-
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
-
<link th:href="@{/css/bootstrap-table.css}" rel="stylesheet"/>
-
<link th:href="@{/font-awesome/css/font-awesome.min.css}" rel="stylesheet"/>
-
<link th:href="@{/css/bootstrap-datetimepicker.css}" rel="stylesheet"/>
-
<link th:href="@{/css/bootstrapValidator.min.css}" rel="stylesheet"/>
-
<link th:href="@{/css/fileinput.css}" rel="stylesheet"/>
-
<link th:href="@{/css/fileinput-rtl.css}" rel="stylesheet"/>
-
<link th:href="@{/css/theme.css}" rel="stylesheet"/>
-
<link th:href="@{/css/zTreeStyle/metro.css}" rel="stylesheet"/>
-
-
-
<script th:src="@{/js/sockjs.min.js}"></script>
-
<script th:src="@{/js/stomp.min.js}"></script>
-
<script th:src="@{/js/jquery.js}"></script>
-
<script th:src="@{/js/distpicker/distpicker.data.js}"></script>
-
<script th:src="@{/js/distpicker/distpicker.js}"></script>
-
<script th:src="@{/js/websocket/socketUtil.js}"></script>
-
<script th:src="@{/js/bootstrap.min.js}"></script>
-
<script th:src="@{/js/bootstrap/nav/nav.js}"></script>
-
<script th:src="@{/js/bootstrap/tab/bootstrap-tab.js}"></script>
-
<script th:src="@{/js/bootstrap/tree/tree.js}"></script>
-
<script th:src="@{/js/bootstrap/alert/alert.js}"></script>
-
<script th:src="@{/js/bootstrap/table/bootstrap-table.js}"></script>
-
<script th:src="@{/js/bootstrap/date/bootstrap-datetimepicker.js}"></script>
-
<script th:src="@{/js/bootstrap/validator/bootstrapValidator.min.js}"></script>
-
<script th:src="@{/js/bootstrap/upload/fileinput.min.js}"></script>
-
<script th:src="@{/js/bootstrap/upload/plugins/sortable.js}"></script>
-
<script th:src="@{/js/bootstrap/upload/locales/zh.js}"></script>
-
<script th:src="@{/js/bootstrap/upload/theme.js}"></script>
-
<script th:src="@{/js/bootstrap/ztree/jquery.ztree.all-3.5.min.js}"></script>
-
<script th:src="@{/js/bootstrap/checkbox/checkbox.js}"></script>
-
<script th:src="@{/js/ajaxutil/ajaxUtil.js}"></script>
-
<script th:src="@{/js/dict/dictUtil.js}"></script>
-
<script th:src="@{/js/bootstrap/date/date.prototype.format.js}"></script>
-
<script th:src="@{/js/bootstrap/util/number.pick.util.js}"></script>
-
-
</html>
通过以上的代码的快速生成、修改以及配置我们这才可以正式开发我们的登陆成功以后的首页,首页代码如下:
-
<html xmlns:th="http://www.thymeleaf.org"
-
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
-
<head th:include="include/includebase"></head>
-
<link th:href="@{css/sb-admin.css}" rel="stylesheet"/>
-
<script th:inline="javascript">
-
$(function () {
-
// 页面加载完成以后开启websocket的连接
-
var options = new Array();
-
options.sockurl = ‘/ricky-websocket‘;
-
options.stompClienturl = ‘/ricky/topic/greetings‘;
-
options.login = [[${#authentication.name}]];
-
options.success = function(greeting){
-
var r = eval("("+JSON.parse(greeting.body).content+")")
-
alert(r);
-
// $("#greetings").append("<tr><td>" + JSON.parse(greeting.body).content + "</td></tr>");
-
}
-
$.fn.socketConnect(options);
-
// 初始化nav
-
$.fn.bootstrapNav({index:‘main‘,navTitle:‘XXXX管理系统‘});
-
// 初始化标签页
-
$("#tabContainer").tabs({
-
data: [{
-
id: ‘99999999‘,
-
text: ‘首页‘,
-
url: "home",
-
closeable: false
-
}],
-
showIndex: 0,
-
loadAll: false
-
})
-
//
-
$.fn.bootstrapTree({url:"/user/mainTree",treeId:‘menu_tree‘,tabId:"tabContainer"});
-
$.fn.dictUtil("/dict/loadDict");
-
});
-
</script>
-
<body >
-
<div id="wrapper">
-
-
<!-- Navigation -->
-
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
-
<!-- Brand and toggle get grouped for better mobile display -->
-
<div class="navbar-header" id="navbar_header">
-
-
</div>
-
<!-- Top Menu Items -->
-
<ul class="nav navbar-right top-nav">
-
<li class="dropdown">
-
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-envelope"></i> <b class="caret"></b></a>
-
<ul class="dropdown-menu message-dropdown">
-
<li class="message-preview">
-
<a href="#">
-
<div class="media">
-
<span class="pull-left">
-
<img class="media-object" src="http://placehold.it/50x50" alt="" />
-
</span>
-
<div class="media-body">
-
<h5 class="media-heading"><strong>John Smith</strong>
-
</h5>
-
<p class="small text-muted"><i class="fa fa-clock-o"></i> Yesterday at 4:32 PM</p>
-
<p>Lorem ipsum dolor sit amet, consectetur...</p>
-
</div>
-
</div>
-
</a>
-
</li>
-
<li class="message-preview">
-
<a href="#">
-
<div class="media">
-
<span class="pull-left">
-
<img class="media-object" src="http://placehold.it/50x50" alt="" />
-
</span>
-
<div class="media-body">
-
<h5 class="media-heading"><strong>John Smith</strong>
-
</h5>
-
<p class="small text-muted"><i class="fa fa-clock-o"></i> Yesterday at 4:32 PM</p>
-
<p>Lorem ipsum dolor sit amet, consectetur...</p>
-
</div>
-
</div>
-
</a>
-
</li>
-
<li class="message-preview">
-
<a href="#">
-
<div class="media">
-
<span class="pull-left">
-
<img class="media-object" src="http://placehold.it/50x50" alt="" />
-
</span>
-
<div class="media-body">
-
<h5 class="media-heading"><strong>John Smith</strong>
-
</h5>
-
<p class="small text-muted"><i class="fa fa-clock-o"></i> Yesterday at 4:32 PM</p>
-
<p>Lorem ipsum dolor sit amet, consectetur...</p>
-
</div>
-
</div>
-
</a>
-
</li>
-
<li class="message-footer">
-
<a href="#">Read All New Messages</a>
-
</li>
-
</ul>
-
</li>
-
<li class="dropdown">
-
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-user"></i> <font th:text="${#authentication.name}"></font> <b class="caret"></b></a>
-
<ul class="dropdown-menu">
-
<li>
-
<a href="#" ><i class="fa fa-fw fa-gear"></i> 修改密码 </a>
-
</li>
-
<li class="divider"></li>
-
<li>
-
<a href="/logout" ><i class="fa fa-fw fa-power-off"></i>退 出</a>
-
</li>
-
</ul>
-
</li>
-
</ul>
-
<!-- Sidebar Menu Items - These collapse to the responsive navigation menu on small screens -->
-
<div class="collapse navbar-collapse navbar-ex1-collapse">
-
<ul class="nav navbar-nav side-nav" id="menu_tree">
-
-
</ul>
-
</div>
-
<!-- /.navbar-collapse -->
-
</nav>
-
<div id="page-wrapper" style="border-radius:5px 5px 0 0;">
-
<div id="tabContainer"></div>
-
</div>
-
</div>
-
<!--
-
<div th:text="${#authentication.name}">
-
The value of the "name" property of the authentication object should appear here.
-
</div>
-
这是一个登陆成功以后的首页
-
<div class="row">
-
<div class="col-md-12">
-
<table id="conversation" class="table table-striped">
-
<thead>
-
<tr>
-
<th>Greetings</th>
-
</tr>
-
</thead>
-
<tbody id="greetings">
-
</tbody>
-
</table>
-
</div>
-
</div>
-
-->
-
</body>
-
</html>
那么到此处我们已经完成了整个系统的基础架构的百分80的开发工作了,那么剩下的就是开发我们相应的功能模块。
本章代码的GitHub地址:https://github.com/185594-5-27/csdndemo/tree/master-base-tree
上一篇文章地址:基于springboot+bootstrap+mysql+redis搭建一套完整的权限架构【五】【编写基础代码快速生成工具】
下一篇文章地址:基于springboot+bootstrap+mysql+redis搭建一套完整的权限架构【七】【菜单维护模块】
以上是关于基于springboot+bootstrap+mysql+redis搭建一套完整的权限架构整合springSecurity的主要内容,如果未能解决你的问题,请参考以下文章
基于 Springboot + Vue + Bootstrap 的电影票订票购票系统,可用于毕业设计课程设计练手学习
基于 Springboot + Vue + Bootstrap 的电影票订票购票系统,可用于毕业设计课程设计练手学习
基于springboot+bootstrap+mysql+redis搭建一套完整的权限架构整合springSecurity
bootstrap+springboot实现shiro权限控制的坑
基于springboot+bootstrap+thymeleaf的物联网一站式宠物管理平台(领养救助商城)设计 毕业论文+用户手册+源码清单+项目源码及数据库文件