springboot+spring security+mybaits实现登录权限管理

springboot+spring security+mybaits实现登录权限管理

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/yangl1337905751/article/details/79741695

序:

本文采用springboot+spring security+mybatis来解决登录权限管理的问题。由于是新人,所以在操作方面讲得比较详细。

话不多说,直接来开始我们的项目。

1 创建springboot+spring security+mybatis 项目

这里我们采用了intellIJidea编辑器。

1.1 创建springboot项目(jdk采用1.8版本)

1.2 对项目进行配置

1.3 勾选我们需要的架包依赖

1.4 对项目进行最终的命名及项目位置确定

2 对application.properties以及pom.xml文件进行配置

2.1 application.properties(我们可以随时修改其中数据库的地址及其他相关数据)

 
  1. jdbc.db.driverClassName=com.mysql.cj.jdbc.Driver

  2. jdbc.db.url=jdbc:mysql://localhost:3306/mydemo?serverTimezone=UTC&characterEncoding=utf-8&useSSL=false

  3. jdbc.db.username=root

  4. jdbc.db.password=admin

  5. jdbc.db.maxActive=500

  6.  
  7. logging.level.org.springframework.security= INFO

  8. spring.thymeleaf.cache=false

2.2 pom.xml(若你按照我的方式创建项目有可能运行不起来,可能是架包版本的缘故,可复制我的)

 
  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <project xmlns="http://maven.apache.org/POM/4.0.0"

  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  5. <modelVersion>4.0.0</modelVersion>

  6.  
  7. <groupId>com.example</groupId>

  8. <artifactId>security-mybatis</artifactId>

  9. <version>1.0-SNAPSHOT</version>

  10.  
  11. <parent>

  12. <groupId>org.springframework.boot</groupId>

  13. <artifactId>spring-boot-starter-parent</artifactId>

  14. <version>1.3.0.RELEASE</version>

  15. </parent>

  16.  
  17. <properties>

  18. <start-class>com.us.Application</start-class>

  19. <maven.compiler.target>1.8</maven.compiler.target>

  20. <maven.compiler.source>1.8</maven.compiler.source>

  21. <mybatis.version>3.2.7</mybatis.version>

  22. <mybatis-spring.version>1.2.2</mybatis-spring.version>

  23. </properties>

  24. <dependencies>

  25. <!--springboot-->

  26. <dependency>

  27. <groupId>org.springframework.boot</groupId>

  28. <artifactId>spring-boot-starter-security</artifactId>

  29. </dependency>

  30. <dependency>

  31. <groupId>org.springframework.boot</groupId>

  32. <artifactId>spring-boot-starter-thymeleaf</artifactId>

  33. </dependency>

  34. <dependency>

  35. <groupId>org.thymeleaf.extras</groupId>

  36. <artifactId>thymeleaf-extras-springsecurity4</artifactId>

  37. </dependency>

  38. <!--db-->

  39. <dependency>

  40. <groupId>mysql</groupId>

  41. <artifactId>mysql-connector-java</artifactId>

  42. <version>6.0.5</version>

  43. </dependency>

  44. <dependency>

  45. <groupId>com.mchange</groupId>

  46. <artifactId>c3p0</artifactId>

  47. <version>0.9.5.2</version>

  48. <exclusions>

  49. <exclusion>

  50. <groupId>commons-logging</groupId>

  51. <artifactId>commons-logging</artifactId>

  52. </exclusion>

  53. </exclusions>

  54. </dependency>

  55.  
  56. <!--mybatis-->

  57. <dependency>

  58. <groupId>org.springframework</groupId>

  59. <artifactId>spring-jdbc</artifactId>

  60. </dependency>

  61. <dependency>

  62. <groupId>org.mybatis</groupId>

  63. <artifactId>mybatis</artifactId>

  64. <version>${mybatis.version}</version>

  65. </dependency>

  66. <dependency>

  67. <groupId>org.mybatis</groupId>

  68. <artifactId>mybatis-spring</artifactId>

  69. <version>${mybatis-spring.version}</version>

  70. </dependency>

  71. </dependencies>

  72.  
  73. </project>

 

3 数据库设计

3.1 数据库表的设计,登录比较简单,只有五张表,分别是用户表(sys_user),角色表(sys_role),权限表(sys_permission),角色权限关系表(sys_role_user),角色用户关系表(sys_role_permission).

然后我们往里面填充一点数据

 
  1. insert into SYS_USER (id,username, password) values (1,'admin', 'admin');

  2. insert into SYS_USER (id,username, password) values (2,'user', 'user');

  3.  
  4. insert into SYS_ROLE(id,name) values(1,'ROLE_ADMIN');

  5. insert into SYS_ROLE(id,name) values(2,'ROLE_USER');

  6.  
  7. insert into SYS_ROLE_USER(SYS_USER_ID,ROLES_ID) values(1,1);

  8. insert into SYS_ROLE_USER(SYS_USER_ID,ROLES_ID) values(2,2);

  9.  
  10. BEGIN;

  11. INSERT INTO `Sys_permission` VALUES ('1', 'ROLE_HOME', 'home', '/', null), ('2', 'ROLE_ADMIN', 'user', '/admin', null);

  12. COMMIT;

  13.  
  14. BEGIN;

  15. INSERT INTO `Sys_permission_role` VALUES ('1', '1', '1'), ('2', '1', '2'), ('3', '2', '1');

  16. COMMIT;

3.2 实体类的创建

3.2.1 SysUser.java

 
  1. package com.example.securitymybatis.entity;

  2.  
  3. import java.util.List;

  4. //用户表(sys_user表)

  5. public class SysUser {

  6. //主键id

  7. private Integer id;

  8. //用户名

  9. private String username;

  10. //登录密码

  11. private String password;

  12.  
  13. private List<SysRole> roles;

  14.  
  15. public Integer getId() {

  16. return id;

  17. }

  18.  
  19. public void setId(Integer id) {

  20. this.id = id;

  21. }

  22.  
  23. public String getUsername() {

  24. return username;

  25. }

  26.  
  27. public void setUsername(String username) {

  28. this.username = username;

  29. }

  30.  
  31. public String getPassword() {

  32. return password;

  33. }

  34.  
  35. public void setPassword(String password) {

  36. this.password = password;

  37. }

  38.  
  39. public List<SysRole> getRoles() {

  40. return roles;

  41. }

  42.  
  43. public void setRoles(List<SysRole> roles) {

  44. this.roles = roles;

  45. }

  46. }

3.2.2 SysRole.java

 
  1. package com.example.securitymybatis.entity;

  2. //角色表(sys_role表)

  3. public class SysRole {

  4. //主键id

  5. private Integer id;

  6. //角色名称

  7. private String name;

  8. public Integer getId() {

  9. return id;

  10. }

  11. public void setId(Integer id) {

  12. this.id = id;

  13. }

  14. public String getName() {

  15. return name;

  16. }

  17. public void setName(String name) {

  18. this.name = name;

  19. }

  20. }

3.2.3 Permission.java

 
 
  1. package com.example.securitymybatis.entity;

  2. //权限表(sys_permission表)

  3. public class Permission {

  4. //主键id

  5. private int id;

  6. //权限名称

  7. private String name;

  8.  
  9. //权限描述

  10. private String descritpion;

  11.  
  12. //授权链接

  13. private String url;

  14.  
  15. //父节点id

  16. private int pid;

  17.  
  18. //请求方式

  19. private String method;

  20.  
  21.  
  22. public int getId() {

  23. return id;

  24. }

  25.  
  26. public void setId(int id) {

  27. this.id = id;

  28. }

  29.  
  30. public String getName() {

  31. return name;

  32. }

  33.  
  34. public void setName(String name) {

  35. this.name = name;

  36. }

  37.  
  38. public String getDescritpion() {

  39. return descritpion;

  40. }

  41.  
  42. public void setDescritpion(String descritpion) {

  43. this.descritpion = descritpion;

  44. }

  45.  
  46. public String getUrl() {

  47. return url;

  48. }

  49.  
  50. public void setUrl(String url) {

  51. this.url = url;

  52. }

  53.  
  54. public int getPid() {

  55. return pid;

  56. }

  57.  
  58. public void setPid(int pid) {

  59. this.pid = pid;

  60. }

  61.  
  62. public String getMethod() {

  63. return method;

  64. }

  65.  
  66. public void setMethod(String method) {

  67. this.method = method;

  68. }

  69. }

3.2.4 Message.java

 
  1. package com.example.securitymybatis.entity;

  2. //中间信息表(无数据库实体表,只用来专递中间信息)

  3. public class Message {

  4. //信息标题

  5. private String title;

  6. //信息主体

  7. private String content;

  8. //额外信息

  9. private String etraInfo;

  10.  
  11. public Message(String title, String content, String etraInfo) {

  12. super();

  13. this.title = title;

  14. this.content = content;

  15. this.etraInfo = etraInfo;

  16. }

  17. public String getTitle() {

  18. return title;

  19. }

  20. public void setTitle(String title) {

  21. this.title = title;

  22. }

  23. public String getContent() {

  24. return content;

  25. }

  26. public void setContent(String content) {

  27. this.content = content;

  28. }

  29. public String getEtraInfo() {

  30. return etraInfo;

  31. }

  32. public void setEtraInfo(String etraInfo) {

  33. this.etraInfo = etraInfo;

  34. }

  35. }

4 config配置

4.1 DBconfig.java配置

 
  1. package com.example.securitymybatis.config;

  2.  
  3. import com.mchange.v2.c3p0.ComboPooledDataSource;

  4. import org.springframework.beans.factory.annotation.Autowired;

  5. import org.springframework.context.annotation.Bean;

  6. import org.springframework.context.annotation.Configuration;

  7. import org.springframework.core.env.Environment;

  8. import java.beans.PropertyVetoException;

  9. //配置数据源

  10. @Configuration

  11. public class DBconfig {

  12. @Autowired

  13. private Environment env;

  14.  
  15. @Bean(name="dataSource")

  16. public ComboPooledDataSource dataSource() throws PropertyVetoException {

  17. ComboPooledDataSource dataSource = new ComboPooledDataSource();

  18. dataSource.setDriverClass(env.getProperty("jdbc.db.driverClassName"));

  19. dataSource.setJdbcUrl(env.getProperty("jdbc.db.url"));

  20. dataSource.setUser(env.getProperty("jdbc.db.username"));

  21. dataSource.setPassword(env.getProperty("jdbc.db.password"));

  22. dataSource.setMaxPoolSize(20);

  23. dataSource.setMinPoolSize(5);

  24. dataSource.setInitialPoolSize(10);

  25. dataSource.setMaxIdleTime(300);

  26. dataSource.setAcquireIncrement(5);

  27. dataSource.setIdleConnectionTestPeriod(60);

  28. return dataSource;

  29. }

  30. }

4.2 MybaitsConfig.java配置

 
  1. package com.example.securitymybatis.config;

  2.  
  3. import org.mybatis.spring.SqlSessionFactoryBean;

  4. import org.springframework.beans.factory.annotation.Autowired;

  5. import org.springframework.context.ApplicationContext;

  6. import org.springframework.context.annotation.Bean;

  7. import org.springframework.context.annotation.ComponentScan;

  8. import org.springframework.context.annotation.Configuration;

  9. import javax.sql.DataSource;

  10. //扫描mapper文件

  11. @Configuration

  12. @ComponentScan

  13. public class MybatisConfig {

  14.  
  15. @Autowired

  16. private DataSource dataSource;

  17.  
  18. @Bean(name = "sqlSessionFactory")

  19. public SqlSessionFactoryBean sqlSessionFactory(ApplicationContext applicationContext) throws Exception {

  20. SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();

  21. sessionFactory.setDataSource(dataSource);

  22. // sessionFactory.setPlugins(new Interceptor[]{new PageInterceptor()});

  23. sessionFactory.setMapperLocations(applicationContext.getResources("classpath*:mapper/*.xml"));

  24. return sessionFactory;

  25. }

  26. }

4.3 MybatisScannerConfig.java配置

 
  1. package com.example.securitymybatis.config;

  2.  
  3. import org.mybatis.spring.mapper.MapperScannerConfigurer;

  4. import org.springframework.context.annotation.Bean;

  5. import org.springframework.context.annotation.Configuration;

  6. //扫描dao层文件

  7. @Configuration

  8. public class MybatisScannerConfig {

  9. @Bean

  10. public MapperScannerConfigurer MapperScannerConfigurer() {

  11. MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();

  12. mapperScannerConfigurer.setBasePackage("com.example.securitymybatis.dao");

  13. mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");

  14. return mapperScannerConfigurer;

  15. }

  16. }

4.4 TransactionConfig.java配置

 
  1. package com.example.securitymybatis.config;

  2.  
  3. import org.springframework.beans.factory.annotation.Autowired;

  4. import org.springframework.context.annotation.Bean;

  5. import org.springframework.context.annotation.ComponentScan;

  6. import org.springframework.context.annotation.Configuration;

  7. import org.springframework.jdbc.datasource.DataSourceTransactionManager;

  8. import org.springframework.transaction.PlatformTransactionManager;

  9. import org.springframework.transaction.annotation.TransactionManagementConfigurer;

  10. import javax.sql.DataSource;

  11. //开启事务管理

  12. @Configuration

  13. @ComponentScan

  14. public class TransactionConfig implements TransactionManagementConfigurer {

  15. @Autowired

  16. private DataSource dataSource;

  17.  
  18. @Bean(name = "transactionManager")

  19. @Override

  20. public PlatformTransactionManager annotationDrivenTransactionManager() {

  21. return new DataSourceTransactionManager(dataSource);

  22. }

  23.  
  24. }

4.5 WebMvcConfig.java 配置

 
  1. package com.example.securitymybatis.config;

  2.  
  3. import org.springframework.context.annotation.Configuration;

  4. import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;

  5. import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

  6. //web视图管理

  7. @Configuration

  8. public class WebMvcConfig extends WebMvcConfigurerAdapter {

  9.  
  10. @Override

  11. public void addViewControllers(ViewControllerRegistry registry) {

  12. registry.addViewController("/login").setViewName("login");

  13. }

  14. }

 
  1. package com.example.securitymybatis.config;

  2.  
  3. import org.springframework.context.annotation.Configuration;

  4. import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;

  5. import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

  6. //web视图管理

  7. @Configuration

  8. public class WebMvcConfig extends WebMvcConfigurerAdapter {

  9.  
  10. @Override

  11. public void addViewControllers(ViewControllerRegistry registry) {

  12. registry.addViewController("/login").setViewName("login");

  13. }

  14. }

4.6 WebSecurityConfig.java 配置(本文核心配置,请看注释)

 
  1. package com.example.securitymybatis.config;

  2.  
  3. import com.example.securitymybatis.security.MyFilterSecurityInterceptor;

  4. import com.example.securitymybatis.security.UserService;

  5. import org.springframework.beans.factory.annotation.Autowired;

  6. import org.springframework.context.annotation.Bean;

  7. import org.springframework.context.annotation.Configuration;

  8. import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;

  9. import org.springframework.security.config.annotation.web.builders.HttpSecurity;

  10. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

  11. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

  12. import org.springframework.security.core.userdetails.UserDetailsService;

  13. import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;

  14.  
  15. //业务核心

  16. @Configuration

  17. @EnableWebSecurity

  18. public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  19. @Autowired

  20. private MyFilterSecurityInterceptor myFilterSecurityInterceptor;

  21.  
  22. @Bean

  23. UserDetailsService customUserService(){ //注册UserDetailsService 的bean

  24. return new UserService();

  25. }

  26. @Override

  27. protected void configure(AuthenticationManagerBuilder auth) throws Exception {

  28. auth.userDetailsService(customUserService()); //user Details Service验证

  29.  
  30. }

  31. @Override

  32. protected void configure(HttpSecurity http) throws Exception {

  33. // // http.authorizeRequests()每个匹配器按照它们被声明的顺序被考虑。

  34. http

  35. .authorizeRequests()

  36. // 所有用户均可访问的资源

  37. .antMatchers("/css/**", "/js/**", "/images/**", "/webjars/**", "**/favicon.ico").permitAll()

  38. // ROLE_USER的权限才能访问的资源

  39. .antMatchers("/user/**").hasRole("USER")

  40. // 任何尚未匹配的URL只需要验证用户即可访问

  41. .anyRequest().authenticated()

  42. .and()

  43. .formLogin()

  44. // 指定登录页面,授予所有用户访问登录页面

  45. .loginPage("/login")

  46. //设置默认登录成功跳转页面,错误回到login界面

  47. .defaultSuccessUrl("/index").failureUrl("/login?error").permitAll()

  48. .and()

  49. //开启cookie保存用户数据

  50. .rememberMe()

  51. //设置cookie有效期

  52. .tokenValiditySeconds(60 * 60 * 24 * 7)

  53. //设置cookie的私钥

  54. .key("security")

  55. .and()

  56. .logout()

  57. .permitAll();

  58. //登录拦截器

  59. http.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class)

  60. //springsecurity4自动开启csrf(跨站请求伪造)与restful冲突

  61. .csrf().disable();

  62. }

  63. }

完成config后我们开始从自底向上的方式来编写我们的登陆功能。

5 mapper的配置

5.1 UserDaoMapper.xml 配置

 
  1. <?xml version="1.0" encoding="UTF-8" ?>

  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

  3. <mapper namespace="com.example.securitymybatis.dao.UserDao">

  4. <resultMap id="userMap" type="com.example.securitymybatis.entity.SysUser">

  5. <id property="id" column="ID"/>

  6. <result property="username" column="username"/>

  7. <result property="password" column="PASSWORD"/>

  8. <collection property="roles" ofType="com.example.securitymybatis.entity.SysRole">

  9. <result column="name" property="name"/>

  10. </collection>

  11.  
  12. </resultMap>

  13. <select id="findByUserName" parameterType="String" resultMap="userMap">

  14. select u.*

  15. ,r.name

  16. from sys_user u

  17. LEFT JOIN sys_role_user sru on u.id= sru.sys_user_id

  18. LEFT JOIN sys_role r on sru.sys_role_id=r.id

  19. where username= #{username}

  20. </select>

  21. </mapper>

5.2 PermissionDaoMapper.xml 配置

 
  1. <?xml version="1.0" encoding="UTF-8" ?>

  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

  3. <mapper namespace="com.example.securitymybatis.dao.PermissionDao">

  4. <select id="findAll" resultType="com.example.securitymybatis.entity.Permission">

  5. SELECT * from Sys_permission ;

  6. </select>

  7.  
  8. <select id="findByAdminUserId" parameterType="int" resultType="com.example.securitymybatis.entity.Permission">

  9. select p.*

  10. from sys_user u

  11. LEFT JOIN sys_role_user sru on u.id= sru.sys_user_id

  12. LEFT JOIN sys_role r on sru.sys_role_id=r.id

  13. LEFT JOIN sys_permission_role spr on spr.role_id=r.id

  14. LEFT JOIN sys_permission p on p.id =spr.permission_id

  15. where u.id=#{userId}

  16. </select>

  17. </mapper>

6 dao层接口配置

6.1 UserDao.java

 
  1. package com.example.securitymybatis.dao;

  2.  
  3. import com.example.securitymybatis.entity.SysUser;

  4.  
  5. public interface UserDao {

  6. public SysUser findByUserName(String username);

  7. }

6.2 PermissionDao.java

 
  1. package com.example.securitymybatis.dao;

  2.  
  3. import com.example.securitymybatis.entity.Permission;

  4.  
  5. import java.util.List;

  6.  
  7. public interface PermissionDao {

  8. public List<Permission> findAll();

  9. public List<Permission> findByAdminUserId(int userId);

  10. }

7 serivice 层配置

7.1 UserService.java(其中会用到后面写到的方法)

 
  1. package com.example.securitymybatis.security;

  2.  
  3. import com.example.securitymybatis.dao.PermissionDao;

  4. import com.example.securitymybatis.dao.UserDao;

  5. import com.example.securitymybatis.entity.Permission;

  6. import com.example.securitymybatis.entity.SysUser;

  7. import org.springframework.beans.factory.annotation.Autowired;

  8. import org.springframework.security.core.GrantedAuthority;

  9. import org.springframework.security.core.authority.SimpleGrantedAuthority;

  10. import org.springframework.security.core.userdetails.UserDetails;

  11. import org.springframework.security.core.userdetails.UserDetailsService;

  12. import org.springframework.security.core.userdetails.UsernameNotFoundException;

  13. import org.springframework.stereotype.Service;

  14. import org.springframework.security.core.userdetails.User;

  15.  
  16. import java.util.ArrayList;

  17. import java.util.List;

  18.  
  19. @Service

  20. public class UserService implements UserDetailsService { //自定义UserDetailsService 接口

  21.  
  22. @Autowired

  23. UserDao userDao;

  24. @Autowired

  25. PermissionDao permissionDao;

  26.  
  27. @Override

  28. public UserDetails loadUserByUsername(String username) { //重写loadUserByUsername 方法获得 userdetails 类型用户

  29.  
  30. SysUser user = userDao.findByUserName(username);

  31. if (user != null) {

  32. List<Permission> permissions = permissionDao.findByAdminUserId(user.getId());

  33. List<GrantedAuthority> grantedAuthorities = new ArrayList <>();

  34. for (Permission permission : permissions) {

  35. if (permission != null && permission.getName()!=null) {

  36.  
  37. GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permission.getName());

  38. //1:此处将权限信息添加到 GrantedAuthority 对象中,在后面进行全权限验证时会使用GrantedAuthority 对象。

  39. grantedAuthorities.add(grantedAuthority);

  40. }

  41. }

  42. return new User(user.getUsername(), user.getPassword(), grantedAuthorities);

  43. } else {

  44. throw new UsernameNotFoundException("admin: " + username + " do not exist!");

  45. }

  46. }

  47. }

8 controller层配置

8.1 LoginController.java(其中有几个方法的权限是管理员才有的)

 
  1. package com.example.securitymybatis.controller;

  2.  
  3. import com.example.securitymybatis.entity.Message;

  4. import org.springframework.stereotype.Controller;

  5. import org.springframework.ui.Model;

  6. import org.springframework.web.bind.annotation.RequestMapping;

  7. import org.springframework.web.bind.annotation.RequestMethod;

  8. import org.springframework.web.bind.annotation.ResponseBody;

  9.  
  10. @Controller

  11. public class LoginController {

  12.  
  13. @RequestMapping("/index")

  14. public String index(Model model){

  15. Message msg = new Message("测试标题","测试内容","额外信息,只对管理员显示");

  16. model.addAttribute("msg", msg);

  17. return "index";

  18. }

  19. @RequestMapping("/admin")

  20. @ResponseBody

  21. public String hello(){

  22. return "hello admin";

  23. }

  24.  
  25. @RequestMapping("/login")

  26. public String login(){

  27. return "login";

  28. }

  29.  
  30. @RequestMapping(value = "/user", method = RequestMethod.GET)

  31. @ResponseBody

  32. public String getList(){

  33. return "hello getList";

  34. }

  35.  
  36.  
  37. @RequestMapping(value = "/user", method = RequestMethod.POST)

  38. @ResponseBody

  39. public String save(){

  40. return "hello save";

  41. }

  42.  
  43.  
  44. @RequestMapping(value = "/user", method = RequestMethod.PUT)

  45. @ResponseBody

  46. public String update(){

  47. return "hello update";

  48. }

  49. }

  50.  

9 security 配置(核心)

9.1 MyAccessDecisionManager.java(授权管理器)

 
  1. package com.example.securitymybatis.security;

  2.  
  3. import org.springframework.security.access.AccessDecisionManager;

  4. import org.springframework.security.access.AccessDeniedException;

  5. import org.springframework.security.access.ConfigAttribute;

  6. import org.springframework.security.authentication.InsufficientAuthenticationException;

  7. import org.springframework.security.core.Authentication;

  8. import org.springframework.security.core.GrantedAuthority;

  9. import org.springframework.stereotype.Service;

  10.  
  11. import java.util.Collection;

  12. import java.util.Iterator;

  13.  
  14. @Service

  15. public class MyAccessDecisionManager implements AccessDecisionManager {

  16.  
  17. // decide 方法是判定是否拥有权限的决策方法,

  18. //authentication 是释CustomUserService中循环添加到 GrantedAuthority 对象中的权限信息集合.

  19. //object 包含客户端发起的请求的requset信息,可转换为 HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();

  20. //configAttributes 为MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法返回的结果,此方法是为了判定用户请求的url 是否在权限表中,如果在权限表中,则返回给 decide 方法,用来判定用户是否有此权限。如果不在权限表中则放行。

  21. @Override

  22. public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {

  23.  
  24. if(null== configAttributes || configAttributes.size() <=0) {

  25. return;

  26. }

  27. ConfigAttribute c;

  28. String needRole;

  29. for(Iterator<ConfigAttribute> iter = configAttributes.iterator(); iter.hasNext(); ) {

  30. c = iter.next();

  31. needRole = c.getAttribute();

  32. for(GrantedAuthority ga : authentication.getAuthorities()) {//authentication 为在注释1 中循环添加到 GrantedAuthority 对象中的权限信息集合

  33. if(needRole.trim().equals(ga.getAuthority())) {

  34. return;

  35. }

  36. }

  37. }

  38. throw new AccessDeniedException("no right");

  39. }

  40.  
  41. @Override

  42. public boolean supports(ConfigAttribute attribute) {

  43. return true;

  44. }

  45.  
  46. @Override

  47. public boolean supports(Class<?> clazz) {

  48. return true;

  49. }

  50. }

9.2 MyFilterSecurityInterceptor.java (自定义拦截器)

 
  1. package com.example.securitymybatis.security;

  2.  
  3. import org.springframework.beans.factory.annotation.Autowired;

  4. import org.springframework.security.access.SecurityMetadataSource;

  5. import org.springframework.security.access.intercept.AbstractSecurityInterceptor;

  6. import org.springframework.security.access.intercept.InterceptorStatusToken;

  7. import org.springframework.security.web.FilterInvocation;

  8. import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

  9. import org.springframework.stereotype.Service;

  10.  
  11. import javax.servlet.*;

  12. import java.io.IOException;

  13.  
  14. @Service

  15. public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {

  16.  
  17.  
  18. @Autowired

  19. private FilterInvocationSecurityMetadataSource securityMetadataSource;

  20.  
  21. @Autowired

  22. public void setMyAccessDecisionManager(MyAccessDecisionManager myAccessDecisionManager) {

  23. super.setAccessDecisionManager(myAccessDecisionManager);

  24. }

  25.  
  26.  
  27. @Override

  28. public void init(FilterConfig filterConfig) throws ServletException {

  29.  
  30. }

  31.  
  32. @Override

  33. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

  34.  
  35. FilterInvocation fi = new FilterInvocation(request, response, chain);

  36. invoke(fi);

  37. }

  38.  
  39.  
  40. public void invoke(FilterInvocation fi) throws IOException, ServletException {

  41. //fi里面有一个被拦截的url

  42. //里面调用MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限

  43. //再调用MyAccessDecisionManager的decide方法来校验用户的权限是否足够

  44. InterceptorStatusToken token = super.beforeInvocation(fi);

  45. try {

  46. //执行下一个拦截器

  47. fi.getChain().doFilter(fi.getRequest(), fi.getResponse());

  48. } finally {

  49. super.afterInvocation(token, null);

  50. }

  51. }

  52.  
  53. @Override

  54. public void destroy() {

  55.  
  56. }

  57.  
  58. @Override

  59. public Class<?> getSecureObjectClass() {

  60. return FilterInvocation.class;

  61. }

  62.  
  63. @Override

  64. public SecurityMetadataSource obtainSecurityMetadataSource() {

  65. return this.securityMetadataSource;

  66. }

  67. }

9.3 MyInvocationSecurityMetadataSourceService.java(获取被拦截url所需的全部权限的方法)

 
  1. package com.example.securitymybatis.security;

  2.  
  3. import com.example.securitymybatis.dao.PermissionDao;

  4. import com.example.securitymybatis.entity.Permission;

  5. import org.springframework.beans.factory.annotation.Autowired;

  6. import org.springframework.security.access.ConfigAttribute;

  7. import org.springframework.security.access.SecurityConfig;

  8. import org.springframework.security.web.FilterInvocation;

  9. import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

  10. import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

  11. import org.springframework.stereotype.Service;

  12.  
  13. import javax.servlet.http.HttpServletRequest;

  14. import java.util.*;

  15.  
  16. @Service

  17. public class MyInvocationSecurityMetadataSourceService implements

  18. FilterInvocationSecurityMetadataSource {

  19.  
  20. @Autowired

  21. private PermissionDao permissionDao;

  22.  
  23. private HashMap<String, Collection<ConfigAttribute>> map =null;

  24.  
  25. /**

  26. * 加载权限表中所有权限

  27. */

  28. public void loadResourceDefine(){

  29. map = new HashMap<>();

  30. Collection<ConfigAttribute> array;

  31. ConfigAttribute cfg;

  32. List<Permission> permissions = permissionDao.findAll();

  33. for(Permission permission : permissions) {

  34. array = new ArrayList<>();

  35. cfg = new SecurityConfig(permission.getName());

  36. //此处只添加了用户的名字,其实还可以添加更多权限的信息,例如请求方法到ConfigAttribute的集合中去。此处添加的信息将会作为MyAccessDecisionManager类的decide的第三个参数。

  37. array.add(cfg);

  38. //用权限的getUrl() 作为map的key,用ConfigAttribute的集合作为 value,

  39. map.put(permission.getUrl(), array);

  40. }

  41.  
  42. }

  43.  
  44. //此方法是为了判定用户请求的url 是否在权限表中,如果在权限表中,则返回给 decide 方法,用来判定用户是否有此权限。如果不在权限表中则放行。

  45. @Override

  46. public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {

  47. if(map ==null) loadResourceDefine();

  48. //object 中包含用户请求的request 信息

  49. HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();

  50. AntPathRequestMatcher matcher;

  51. String resUrl;

  52. for(Iterator<String> iter = map.keySet().iterator(); iter.hasNext(); ) {

  53. resUrl = iter.next();

  54. matcher = new AntPathRequestMatcher(resUrl);

  55. if(matcher.matches(request)) {

  56. return map.get(resUrl);

  57. }

  58. }

  59. return null;

  60. }

  61.  
  62. @Override

  63. public Collection<ConfigAttribute> getAllConfigAttributes() {

  64. return null;

  65. }

  66.  
  67. @Override

  68. public boolean supports(Class<?> clazz) {

  69. return true;

  70. }

  71. }

如上所示security的拦截器就配好了,如果有看不懂的地方,可在网上搜security拦截器,我这里就不一一详细解释了。

10 界面代码

10.1 login.html

 
  1. <!DOCTYPE html>

  2. <html xmlns:th="http://www.thymeleaf.org">

  3. <head>

  4. <meta content="text/html;charset=UTF-8"/>

  5. <title>登录页面</title>

  6. <link rel="stylesheet" th:href="@{css/bootstrap.min.css}"/>

  7. <style type="text/css">

  8. body {

  9. padding-top: 50px;

  10. }

  11. .starter-template {

  12. padding: 40px 15px;

  13. text-align: center;

  14. }

  15. .form-group input{

  16. margin: auto;

  17. width: 550px;

  18. }

  19. </style>

  20. </head>

  21. <body>

  22.  
  23. <nav class="navbar navbar-inverse navbar-fixed-top">

  24. <div class="container">

  25. <div class="navbar-header">

  26. <a class="navbar-brand" href="#">Spring Security演示</a>

  27. </div>

  28. <div id="navbar" class="collapse navbar-collapse">

  29. <ul class="nav navbar-nav">

  30. <li><a th:href="@{/}"> 首页 </a></li>

  31.  
  32. </ul>

  33. </div><!--/.nav-collapse -->

  34. </div>

  35. </nav>

  36. <div class="container">

  37.  
  38. <div class="starter-template">

  39. <p th:if="${param.logout}" class="bg-warning">已成功注销</p><!-- 1 -->

  40. <p th:if="${param.error}" class="bg-danger">有错误,请重试</p> <!-- 2 -->

  41. <h2>使用账号密码登录</h2>

  42. <form name="form" th:action="@{/login}" action="/login" method="POST"> <!-- 3 -->

  43. <div class="form-group">

  44. <label for="username">账号</label>

  45. <input type="text" class="form-control" name="username" value="" placeholder="账号" />

  46. </div>

  47. <div class="form-group">

  48. <label for="password">密码</label>

  49. <input type="password" class="form-control" name="password" placeholder="密码" />

  50. </div>

  51. <input type="submit" id="login" value="Login" class="btn btn-primary" />

  52. </form>

  53. </div>

  54. </div>

  55. </body>

  56. </html>

10.2 index.html

 
  1. <!DOCTYPE html>

  2. <html xmlns:th="http://www.thymeleaf.org"

  3. xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">

  4. <head>

  5. <meta content="text/html;charset=UTF-8"/>

  6. <title sec:authentication="name"></title>

  7. <link rel="stylesheet" th:href="@{css/bootstrap.min.css}" />

  8. <style type="text/css">

  9. body {

  10. padding-top: 50px;

  11. }

  12. .starter-template {

  13. padding: 40px 15px;

  14. text-align: center;

  15. }

  16. </style>

  17. </head>

  18. <body>

  19. <nav class="navbar navbar-inverse navbar-fixed-top">

  20. <div class="container">

  21. <div class="navbar-header">

  22. <a class="navbar-brand" href="#">Spring Security演示</a>

  23. </div>

  24. <div id="navbar" class="collapse navbar-collapse">

  25. <ul class="nav navbar-nav">

  26. <li><a th:href="@{/}"> 首页 </a></li>

  27. <li><a th:href="@{/admin}"> admin </a></li>

  28. </ul>

  29. </div><!--/.nav-collapse -->

  30. </div>

  31. </nav>

  32.  
  33.  
  34. <div class="container">

  35.  
  36. <div class="starter-template">

  37. <h1 th:text="${msg.title}"></h1>

  38.  
  39. <p class="bg-primary" th:text="${msg.content}"></p>

  40.  
  41. <div sec:authorize="hasRole('ROLE_ADMIN')"> <!-- 用户类型为ROLE_ADMIN 显示 -->

  42. <p class="bg-info" th:text="${msg.etraInfo}"></p>

  43. </div>

  44.  
  45. <div sec:authorize="hasRole('ROLE_ADMIN')"> <!-- 用户类型为ROLE_ADMIN 显示 -->

  46. <p class="bg-info">恭喜您,您有 ROLE_ADMIN 权限 </p>

  47. </div>

  48.  
  49. <form th:action="@{/logout}" method="post">

  50. <input type="submit" class="btn btn-primary" value="注销"/>

  51. </form>

  52. </div>

  53.  
  54. </div>

  55.  
  56. </body>

  57. </html>

11 整体结构和运行效果。

整个项目的文件结构如上图所示,static下的css文件夹中只有一个bootstrap.min.css文件,网上都能搜到,我就不上传了。

11.1 运行项目,点击右上角的绿色三角形运行项目,不需要配置tomcat.

11.2 打开浏览器,输入localhost:8080即可进入登录界面

11.3 管理员和普通用户登录显示不同的内容

  11.3.1 管理员登录显示

11.3.2 普通用户登录显示

11.4 点击管理员登录后跳转界面上的admin,页面会显示“hello admin”,而普通用户会有403错误。

11.4.1 管理员点击admin

11.4.2 普通用户点击admin

至此,整个springboot+springsecurity+mybaits项目就搭建好了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值