Skip to content

Commit

Permalink
SpringBoot2.0 整合 Security 框架,实现用户权限管理
Browse files Browse the repository at this point in the history
  • Loading branch information
cicadasmile committed Jul 16, 2019
1 parent d2694fb commit 5735b94
Show file tree
Hide file tree
Showing 24 changed files with 650 additions and 1 deletion.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,12 @@
<a href="https://mp.weixin.qq.com/s?__biz=MzU4Njg0MzYwNw==&mid=2247483918&idx=1&sn=189b6f4360c46ca816de85a3205a9fb3&chksm=fdf456b6ca83dfa0f5b0f9c441a8ece1b158792a03e3483ddc702576e9e77f963690c0716e9f&token=1681245262&lang=zh_CN#rd">
10、SpringBoot2.0 整合 FastDFS 中间件,实现文件分布管理</a><br/>

<a href="">
<a href="https://mp.weixin.qq.com/s?__biz=MzU4Njg0MzYwNw==&mid=2247483922&idx=1&sn=f632615588b11840df3a6d17013c7058&chksm=fdf456aaca83dfbc34e13ffd4f05491e6598f3eff7bfeab28b14317cc0f95f939de08eee0c1e&token=1211663505&lang=zh_CN#rd">
11、SpringBoot2.0 整合 Shiro 框架,实现用户权限管理</a><br/>

<a href="">
12、SpringBoot2.0 整合 Security 框架,实现用户权限管理</a><br/>

持续更新中...

## 项目简介
Expand Down
2 changes: 2 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
<module>ware-fast-dfs</module>
<!-- Shiro 权限管理 -->
<module>ware-shiro-auth</module>
<!-- Security 权限管理 -->
<module>ware-security-auth</module>
</modules>

<!-- 依赖版本管理 -->
Expand Down
77 changes: 77 additions & 0 deletions ware-security-auth/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<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">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starters</artifactId>
<version>2.1.3.RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.security.auth</groupId>
<artifactId>ware-security-auth</artifactId>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</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.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>2.1.9</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.13</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
</dependencies>

<!-- 项目构建 -->
<build>
<finalName>${project.artifactId}</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.security.auth;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

@EnableWebSecurity
@SpringBootApplication
public class SecurityApplication {
public static void main(String[] args) {
SpringApplication.run(SecurityApplication.class,args) ;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package com.security.auth.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;

/**
* Druid数据库连接池配置文件
*/
@Configuration
public class DruidConfig {
private static final Logger logger = LoggerFactory.getLogger(DruidConfig.class);

@Value("${spring.datasource.druid.url}")
private String dbUrl;

@Value("${spring.datasource.druid.username}")
private String username;

@Value("${spring.datasource.druid.password}")
private String password;

@Value("${spring.datasource.druid.driverClassName}")
private String driverClassName;

@Value("${spring.datasource.druid.initial-size}")
private int initialSize;

@Value("${spring.datasource.druid.max-active}")
private int maxActive;

@Value("${spring.datasource.druid.min-idle}")
private int minIdle;

@Value("${spring.datasource.druid.max-wait}")
private int maxWait;

@Value("${spring.datasource.druid.pool-prepared-statements}")
private boolean poolPreparedStatements;

@Value("${spring.datasource.druid.max-pool-prepared-statement-per-connection-size}")
private int maxPoolPreparedStatementPerConnectionSize;

@Value("${spring.datasource.druid.time-between-eviction-runs-millis}")
private int timeBetweenEvictionRunsMillis;

@Value("${spring.datasource.druid.min-evictable-idle-time-millis}")
private int minEvictableIdleTimeMillis;

@Value("${spring.datasource.druid.max-evictable-idle-time-millis}")
private int maxEvictableIdleTimeMillis;

@Value("${spring.datasource.druid.validation-query}")
private String validationQuery;

@Value("${spring.datasource.druid.test-while-idle}")
private boolean testWhileIdle;

@Value("${spring.datasource.druid.test-on-borrow}")
private boolean testOnBorrow;

@Value("${spring.datasource.druid.test-on-return}")
private boolean testOnReturn;

@Value("${spring.datasource.druid.filters}")
private String filters;

@Value("{spring.datasource.druid.connection-properties}")
private String connectionProperties;

@Bean //声明其为Bean实例
@Primary //在同样的DataSource中,首先使用被标注的DataSource
public DataSource dataSource() {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(dbUrl);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setDriverClassName(driverClassName);
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setMaxEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setValidationQuery(validationQuery);
datasource.setTestWhileIdle(testWhileIdle);
datasource.setTestOnBorrow(testOnBorrow);
datasource.setTestOnReturn(testOnReturn);
datasource.setPoolPreparedStatements(poolPreparedStatements);
datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
try {
datasource.setFilters(filters);
} catch (Exception e) {
logger.error("druid configuration initialization filter", e);
}
datasource.setConnectionProperties(connectionProperties);
return datasource;
}
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean srb =
new ServletRegistrationBean(new StatViewServlet(),"/druid/*");
// 设置ip白名单
// srb.addInitParameter("allow","127.0.0.1");
// 设置ip黑名单,优先级高于白名单
// srb.addInitParameter("deny","192.168.0.19");
//设置控制台管理用户
srb.addInitParameter("loginUsername","root");
srb.addInitParameter("loginPassword","root");
//是否可以重置数据
srb.addInitParameter("resetEnable","false");
return srb;
}
@Bean
public FilterRegistrationBean statFilter(){
//创建过滤器
FilterRegistrationBean frb =
new FilterRegistrationBean(new WebStatFilter());
//设置过滤器过滤路径
frb.addUrlPatterns("/*");
//忽略过滤的形式
frb.addInitParameter("exclusions",
"*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return frb;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.security.auth.config;
import org.springframework.context.annotation.Bean;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
* EnableWebSecurity注解使得SpringMVC集成了Spring Security的web安全支持
*/
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 权限配置
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
// 配置拦截规则
http.authorizeRequests().antMatchers("/").permitAll()
.antMatchers("/page1/**").hasRole("LEVEL1")
.antMatchers("/page2/**").hasRole("LEVEL2")
.antMatchers("/page3/**").hasRole("LEVEL3");
// 配置登录功能
http.formLogin().usernameParameter("user")
.passwordParameter("pwd")
.loginPage("/userLogin");
// 注销成功跳转首页
http.logout().logoutSuccessUrl("/");
//开启记住我功能
http.rememberMe().rememberMeParameter("remeber");
}
/**
* 自定义认证数据源
*/
@Override
protected void configure(AuthenticationManagerBuilder builder) throws Exception{
builder.userDetailsService(userDetailService())
.passwordEncoder(passwordEncoder());
}
@Bean
public UserDetailServiceImpl userDetailService (){
return new UserDetailServiceImpl () ;
}
/**
* 密码加密
*/
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
/*
* 硬编码几个用户
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("spring").password("123456").roles("LEVEL1","LEVEL2")
.and()
.withUser("summer").password("123456").roles("LEVEL2","LEVEL3")
.and()
.withUser("autumn").password("123456").roles("LEVEL1","LEVEL3");
}
*/
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.security.auth.config;

import com.security.auth.mapper.UserRoleMapper;
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 javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Service
public class UserDetailServiceImpl implements UserDetailsService {
@Resource
private UserRoleMapper userRoleMapper ;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 这里可以捕获异常,使用异常映射,抛出指定的提示信息
// 用户校验的操作
// 假设密码是数据库查询的 123
String password = "$2a$10$XcigeMfToGQ2bqRToFtUi.sG1V.HhrJV6RBjji1yncXReSNNIPl1K";
// 假设角色是数据库查询的
List<String> roleList = userRoleMapper.selectByUserName(username) ;
List<GrantedAuthority> grantedAuthorityList = new ArrayList<>() ;
/*
* Spring Boot 2.0 版本踩坑
* 必须要 ROLE_ 前缀, 因为 hasRole("LEVEL1")判断时会自动加上ROLE_前缀变成 ROLE_LEVEL1 ,
* 如果不加前缀一般就会出现403错误
* 在给用户赋权限时,数据库存储必须是完整的权限标识ROLE_LEVEL1
*/
if (roleList != null && roleList.size()>0){
for (String role : roleList){
grantedAuthorityList.add(new SimpleGrantedAuthority(role)) ;
}
}
return new User(username,password,grantedAuthorityList);
}
}
Loading

0 comments on commit 5735b94

Please sign in to comment.