diff --git a/README.md b/README.md index 45cc7f0..ec86a0a 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,12 @@ 10、SpringBoot2.0 整合 FastDFS 中间件,实现文件分布管理
- + 11、SpringBoot2.0 整合 Shiro 框架,实现用户权限管理
+ +12、SpringBoot2.0 整合 Security 框架,实现用户权限管理
+ 持续更新中... ## 项目简介 diff --git a/pom.xml b/pom.xml index 1727ec4..c1bfffe 100644 --- a/pom.xml +++ b/pom.xml @@ -39,6 +39,8 @@ ware-fast-dfs ware-shiro-auth + + ware-security-auth diff --git a/ware-security-auth/pom.xml b/ware-security-auth/pom.xml new file mode 100644 index 0000000..1663c02 --- /dev/null +++ b/ware-security-auth/pom.xml @@ -0,0 +1,77 @@ + + + + org.springframework.boot + spring-boot-starters + 2.1.3.RELEASE + + 4.0.0 + com.security.auth + ware-security-auth + jar + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 1.3.2 + + + com.baomidou + mybatis-plus + 2.1.9 + + + mysql + mysql-connector-java + 5.1.38 + + + com.alibaba + druid-spring-boot-starter + 1.1.13 + + + com.alibaba + druid + 1.1.10 + + + + + + ${project.artifactId} + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.8 + 1.8 + + + + + + \ No newline at end of file diff --git a/ware-security-auth/src/main/java/com/security/auth/SecurityApplication.java b/ware-security-auth/src/main/java/com/security/auth/SecurityApplication.java new file mode 100644 index 0000000..6ebd96d --- /dev/null +++ b/ware-security-auth/src/main/java/com/security/auth/SecurityApplication.java @@ -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) ; + } +} diff --git a/ware-security-auth/src/main/java/com/security/auth/config/DruidConfig.java b/ware-security-auth/src/main/java/com/security/auth/config/DruidConfig.java new file mode 100644 index 0000000..4526e49 --- /dev/null +++ b/ware-security-auth/src/main/java/com/security/auth/config/DruidConfig.java @@ -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; + } +} \ No newline at end of file diff --git a/ware-security-auth/src/main/java/com/security/auth/config/SecurityConfig.java b/ware-security-auth/src/main/java/com/security/auth/config/SecurityConfig.java new file mode 100644 index 0000000..d76e01f --- /dev/null +++ b/ware-security-auth/src/main/java/com/security/auth/config/SecurityConfig.java @@ -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"); + } + */ +} diff --git a/ware-security-auth/src/main/java/com/security/auth/config/UserDetailServiceImpl.java b/ware-security-auth/src/main/java/com/security/auth/config/UserDetailServiceImpl.java new file mode 100644 index 0000000..ff5bb2c --- /dev/null +++ b/ware-security-auth/src/main/java/com/security/auth/config/UserDetailServiceImpl.java @@ -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 roleList = userRoleMapper.selectByUserName(username) ; + List 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); + } +} \ No newline at end of file diff --git a/ware-security-auth/src/main/java/com/security/auth/controller/PageController.java b/ware-security-auth/src/main/java/com/security/auth/controller/PageController.java new file mode 100644 index 0000000..3358e80 --- /dev/null +++ b/ware-security-auth/src/main/java/com/security/auth/controller/PageController.java @@ -0,0 +1,48 @@ +package com.security.auth.controller; + +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class PageController { + /** + * 首页 + */ + @RequestMapping("/") + public String index (){ + return "home" ; + } + /** + * 登录页 + */ + @RequestMapping("/userLogin") + public String loginPage (){ + return "pages/login" ; + } + /** + * page1 下页面 + */ + @PreAuthorize("hasAuthority('LEVEL1')") + @RequestMapping("/page1/{pageName}") + public String onePage (@PathVariable("pageName") String pageName){ + return "pages/page1/"+pageName ; + } + /** + * page2 下页面 + */ + @PreAuthorize("hasAuthority('LEVEL2')") + @RequestMapping("/page2/{pageName}") + public String twoPage (@PathVariable("pageName") String pageName){ + return "pages/page2/"+pageName ; + } + /** + * page3 下页面 + */ + @PreAuthorize("hasAuthority('LEVEL3')") + @RequestMapping("/page3/{pageName}") + public String threePage (@PathVariable("pageName") String pageName){ + return "pages/page3/"+pageName ; + } +} diff --git a/ware-security-auth/src/main/java/com/security/auth/entity/UserRole.java b/ware-security-auth/src/main/java/com/security/auth/entity/UserRole.java new file mode 100644 index 0000000..9421fad --- /dev/null +++ b/ware-security-auth/src/main/java/com/security/auth/entity/UserRole.java @@ -0,0 +1,25 @@ +package com.security.auth.entity; + +public class UserRole { + private Integer id ; + private String userName ; + private String role ; + public Integer getId() { + return id; + } + public void setId(Integer id) { + this.id = id; + } + public String getUserName() { + return userName; + } + public void setUserName(String userName) { + this.userName = userName; + } + public String getRole() { + return role; + } + public void setRole(String role) { + this.role = role; + } +} diff --git a/ware-security-auth/src/main/java/com/security/auth/mapper/UserRoleMapper.java b/ware-security-auth/src/main/java/com/security/auth/mapper/UserRoleMapper.java new file mode 100644 index 0000000..6c2af83 --- /dev/null +++ b/ware-security-auth/src/main/java/com/security/auth/mapper/UserRoleMapper.java @@ -0,0 +1,11 @@ +package com.security.auth.mapper; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface UserRoleMapper { + List selectByUserName (@Param("userName") String userName) ; +} diff --git a/ware-security-auth/src/main/resources/application.yml b/ware-security-auth/src/main/resources/application.yml new file mode 100644 index 0000000..85ec16f --- /dev/null +++ b/ware-security-auth/src/main/resources/application.yml @@ -0,0 +1,36 @@ +server: + port: 7012 +spring: + application: + name: ware-security-auth + datasource: + type: com.alibaba.druid.pool.DruidDataSource + druid: + driverClassName: com.mysql.jdbc.Driver + url: jdbc:mysql://localhost:3306/spring-boot3?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8 + username: root + password: 123 + initial-size: 10 + max-active: 100 + min-idle: 10 + max-wait: 600 + pool-prepared-statements: true + max-pool-prepared-statement-per-connection-size: 20 + time-between-eviction-runs-millis: 3000 + min-evictable-idle-time-millis: 40000 + max-evictable-idle-time-millis: 60000 + validation-query: SELECT 1 FROM DUAL + # validation-query-timeout: 5000 + test-on-borrow: false + test-on-return: false + test-while-idle: true + connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 + #filters: #配置多个英文逗号分隔(统计,sql注入,log4j过滤) + filters: stat,wall + stat-view-servlet: + enabled: true + url-pattern: /druid/* +# mybatis 配置 +mybatis: + type-aliases-package: com.boot.shiro.entity # 所有Entity别名类所在包 + mapper-locations: classpath:mapper/*.xml # mapper映射文件 \ No newline at end of file diff --git a/ware-security-auth/src/main/resources/mapper/UserRoleMapper.xml b/ware-security-auth/src/main/resources/mapper/UserRoleMapper.xml new file mode 100644 index 0000000..3daa877 --- /dev/null +++ b/ware-security-auth/src/main/resources/mapper/UserRoleMapper.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/ware-security-auth/src/main/resources/security.sql b/ware-security-auth/src/main/resources/security.sql new file mode 100644 index 0000000..38c9bfd --- /dev/null +++ b/ware-security-auth/src/main/resources/security.sql @@ -0,0 +1,9 @@ +CREATE TABLE `user_role` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `user_name` varchar(30) DEFAULT NULL, + `user_role` varchar(50) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户权限表'; + +INSERT INTO `user_role` (`id`, `user_name`, `user_role`) VALUES ('1', 'root', 'ROLE_LEVEL1'); +INSERT INTO `user_role` (`id`, `user_name`, `user_role`) VALUES ('2', 'root', 'ROLE_LEVEL2'); \ No newline at end of file diff --git a/ware-security-auth/src/main/resources/templates/home.html b/ware-security-auth/src/main/resources/templates/home.html new file mode 100644 index 0000000..abbd923 --- /dev/null +++ b/ware-security-auth/src/main/resources/templates/home.html @@ -0,0 +1,49 @@ + + + + + Insert title here + + +

Security      Welcome!

+
+

没登录! 请登录

+
+
+

当前角色有: +

+
+ +
+
+
+ +
+

page1

+ +
+ +
+

page2

+ +
+ +
+

page3

+ +
+ + \ No newline at end of file diff --git a/ware-security-auth/src/main/resources/templates/pages/login.html b/ware-security-auth/src/main/resources/templates/pages/login.html new file mode 100644 index 0000000..1b5f1d0 --- /dev/null +++ b/ware-security-auth/src/main/resources/templates/pages/login.html @@ -0,0 +1,19 @@ + + + + + Insert title here + + +

Security      Login

+
+
+
+ 用户名:
+ 密   码:
+ 记住我
+ +
+
+ + \ No newline at end of file diff --git a/ware-security-auth/src/main/resources/templates/pages/page1/one1.html b/ware-security-auth/src/main/resources/templates/pages/page1/one1.html new file mode 100644 index 0000000..6984e07 --- /dev/null +++ b/ware-security-auth/src/main/resources/templates/pages/page1/one1.html @@ -0,0 +1,12 @@ + + + + +Insert title here + + + 返回首页 +

Page1

+

One1.html

+ + \ No newline at end of file diff --git a/ware-security-auth/src/main/resources/templates/pages/page1/one2.html b/ware-security-auth/src/main/resources/templates/pages/page1/one2.html new file mode 100644 index 0000000..942733a --- /dev/null +++ b/ware-security-auth/src/main/resources/templates/pages/page1/one2.html @@ -0,0 +1,12 @@ + + + + + Insert title here + + +返回首页 +

Page1

+

One2.html

+ + \ No newline at end of file diff --git a/ware-security-auth/src/main/resources/templates/pages/page1/one3.html b/ware-security-auth/src/main/resources/templates/pages/page1/one3.html new file mode 100644 index 0000000..b5e0ff3 --- /dev/null +++ b/ware-security-auth/src/main/resources/templates/pages/page1/one3.html @@ -0,0 +1,12 @@ + + + + + Insert title here + + +返回首页 +

Page1

+

One3.html

+ + \ No newline at end of file diff --git a/ware-security-auth/src/main/resources/templates/pages/page2/one1.html b/ware-security-auth/src/main/resources/templates/pages/page2/one1.html new file mode 100644 index 0000000..8fb57fd --- /dev/null +++ b/ware-security-auth/src/main/resources/templates/pages/page2/one1.html @@ -0,0 +1,12 @@ + + + + +Insert title here + + + 返回首页 +

Page2

+

One1.html

+ + \ No newline at end of file diff --git a/ware-security-auth/src/main/resources/templates/pages/page2/one2.html b/ware-security-auth/src/main/resources/templates/pages/page2/one2.html new file mode 100644 index 0000000..f24625b --- /dev/null +++ b/ware-security-auth/src/main/resources/templates/pages/page2/one2.html @@ -0,0 +1,12 @@ + + + + + Insert title here + + +返回首页 +

Page2

+

One2.html

+ + \ No newline at end of file diff --git a/ware-security-auth/src/main/resources/templates/pages/page2/one3.html b/ware-security-auth/src/main/resources/templates/pages/page2/one3.html new file mode 100644 index 0000000..b7270b1 --- /dev/null +++ b/ware-security-auth/src/main/resources/templates/pages/page2/one3.html @@ -0,0 +1,12 @@ + + + + + Insert title here + + +返回首页 +

Page3

+

One3.html

+ + \ No newline at end of file diff --git a/ware-security-auth/src/main/resources/templates/pages/page3/one1.html b/ware-security-auth/src/main/resources/templates/pages/page3/one1.html new file mode 100644 index 0000000..a7f23ae --- /dev/null +++ b/ware-security-auth/src/main/resources/templates/pages/page3/one1.html @@ -0,0 +1,12 @@ + + + + +Insert title here + + + 返回首页 +

Page3

+

One1.html

+ + \ No newline at end of file diff --git a/ware-security-auth/src/main/resources/templates/pages/page3/one2.html b/ware-security-auth/src/main/resources/templates/pages/page3/one2.html new file mode 100644 index 0000000..4370750 --- /dev/null +++ b/ware-security-auth/src/main/resources/templates/pages/page3/one2.html @@ -0,0 +1,12 @@ + + + + + Insert title here + + +返回首页 +

Page3

+

One2.html

+ + \ No newline at end of file diff --git a/ware-security-auth/src/main/resources/templates/pages/page3/one3.html b/ware-security-auth/src/main/resources/templates/pages/page3/one3.html new file mode 100644 index 0000000..b7270b1 --- /dev/null +++ b/ware-security-auth/src/main/resources/templates/pages/page3/one3.html @@ -0,0 +1,12 @@ + + + + + Insert title here + + +返回首页 +

Page3

+

One3.html

+ + \ No newline at end of file