若需要整合我们的springSecurity,一种是直接使用springSecurity自带的权限架构,另外一种是使用我们自己设计的数据架构,本文所阐述的就是使用自己设计的RBAC权限架构,因此我们要事先设计好用户权限架构的PDM如下图所示,并创建我们的数据库:数据库名:hyll_springboot,以及我们的三张表:user、user_role、user_associate_role:
接着打开我们的工程新建如下工程的目录:
接着在我们的sys包底下新建entity和dao这两个包:
同时打开我们的pom.xml引入该工程所需要的所有依赖,接着我们的IDEA会弹出一个框,我们点击import就自动会去maven给我们下载依赖,若你有自己的私有maven则将其指向自己的私有maven,若这边有缺少不懂的直接去我的第一章的github上的源代码中自己去copy下来:
UTF-8
UTF-8
1.8
5.1.41
18.0
1.1.0.Final
com.alibaba
druid-spring-boot-starter
1.1.3
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.3.1
org.mapstruct
mapstruct-jdk8
${org.mapstruct.version}
org.mapstruct
mapstruct-processor
${org.mapstruct.version}
javax.inject
javax.inject
1
net.sf.json-lib
json-lib
2.4
jdk15
org.springframework.boot
spring-boot-starter-websocket
org.springframework.boot
spring-boot-starter-security
org.thymeleaf.extras
thymeleaf-extras-springsecurity4
net.sourceforge.nekohtml
nekohtml
1.9.22
org.springframework.boot
spring-boot-starter-redis
1.3.8.RELEASE
org.springframework.boot
spring-boot-starter-cache
net.sf.ehcache
ehcache
org.springframework.boot
spring-boot-starter-data-rest
org.springframework.boot
spring-boot-starter-data-jpa
mysql
mysql-connector-java
${mysql.version}
com.google.guava
guava
${guava.version}
org.springframework.boot
spring-boot-starter-thymeleaf
org.springframework.boot
spring-boot-starter-websocket
org.springframework.boot
spring-boot-starter-test
test
javax.servlet
javax.servlet-api
3.1.0
provided
org.springframework.boot
spring-boot-starter-tomcat
1.3.5.RELEASE
provided
org.springframework.boot
spring-boot-devtools
true
com.xiaoleilu
hutool-all
3.0.9
io.springfox
springfox-swagger2
2.6.1
io.springfox
springfox-swagger-ui
2.6.1
com.vaadin.external.google
android-json
0.0.20131108.vaadin1
同时在我们的entity包底下新建我们刚刚的三个实体:
/**
*@author linzf
**/
public class User implements UserDetails {
public User(){
super();
}
public User(int id){
this.id = id;
}
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 roles;
// 权限集合数据
private String roleArray;
public String getRoleArray() {
return roleArray;
}
public void setRoleArray(String roleArray) {
this.roleArray = 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;
}
@Override
public Collection extends GrantedAuthority> getAuthorities() {
List auths = new ArrayList();
if(this.getRoles()!=null){
List roles=this.getRoles();
for(UserRole role:roles){
if(role.getName()!=null){
auths.add(new SimpleGrantedAuthority(role.getName()));
}
}
}
return auths;
}
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return this.getUserName();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public List getRoles() {
return roles;
}
public void setRoles(List roles) {
this.roles = roles;
}
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;
}
/**
* 功能描述:组装角色数据集合
* @param roleArray
*/
public void packagingRoles(String roleArray){
List roles = new ArrayList();
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);
}
}
/**
*@author linzf
**/
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;
}
}
/**
*@author linzf
**/
public class UserAssociateRole {
private int userId;
private long roleId;
public UserAssociateRole(){
super();
}
public UserAssociateRole(int userId,long roleId){
this.userId = userId;
this.roleId = roleId;
}
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;
}
}
/**
*@author linzf
**/
public interface UserDao {
/**
* 功能描述:根据账号来获取用户信息
* @param login
* @return
*/
User findByLogin(String login);
}
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
mybatis-config.xml代码如下所示:
server.port = 8080
#数据库连接配置
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://10.6.71.236:3306/hyll_springboot?characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=haoyunll123
接着我们在resource/mapper目录底下创建一个mybatis_user.xml内容如下:
接着在我们的security增加以下三个类分别是(CustomPasswordEncoder:密码加密类;CustomUserService:登陆逻辑重写类;WebSecurityConfig:security实现配置类):
/**
* spring-security登陆的密码进行MD5加密传到数据库
*/
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");
}
}
/**
* Created by Administrator on 2017/8/4 0004.
*/
public class CustomUserService implements UserDetailsService {
@Inject
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;
}
}
/**
* 实现Security的配置
*/
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled=true)
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
* @throws Exception
*/
@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();
}
}
@Configuration
@MapperScan("com.csdn.demo.*.dao")
public class MyBatisConfig {
}
接着在我们的config目录底下创建我们的WebMvcConfig配置文件如下所示:
/**
* 类描述:springMVC的配置
*/
@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引入那么你们就会发现我们的页面越来越漂亮,运行效果如下图所示:
到此处我们的工程已经上次成功了,我会将本章的代码直接上传到github,大家可以直接下载下来并运行该代码,请大家在运行的时候先把整篇文章过一遍再运行,下一章将讲解如何整合swagger2以及druid这两个配置,本章代码的github地址是:https://github.com/185594-5-27/csdndemo/tree/base-demo,大家在导入项目的时候记得要将版本切换到base-demo版本这个版本才是本章的代码。
上一篇文章地址:基于springboot+bootstrap+mysql+redis搭建一套完整的权限架构【一】【构建工程】
下一篇文章地址:基于springboot+bootstrap+mysql+redis搭建一套完整的权限架构【三】【整合swagger2和druid】
QQ交流群:578746866