Spring Boot在Web应用中基于JdbcRealm安全验证过程

下面我来详细讲解“Spring Boot在Web应用中基于JdbcRealm安全验证过程”的完整攻略。

什么是JdbcRealm

JdbcRealm是Shiro提供的Realm之一,可以用于将用户、角色、权限等信息保存在关系型数据库中。JdbcRealm通过JDBC连接数据库,实现身份认证和授权。

Spring Boot集成JdbcRealm

在Spring Boot应用中,我们可以通过在pom.xml中引入shiro-spring-boot-start和spring-jdbc包来实现JdbcRealm的集成。

在application.properties文件中,我们需要配置数据库连接信息和Shiro的配置信息,示例如下:

# 数据库连接信息
spring.datasource.url=jdbc:mysql://localhost:3306/shiro_db?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=

# Shiro配置信息
shiro.jdbc.authcSql=select password from user where username=?
shiro.jdbc.rolesSql=select role_name from user_role where username=?
shiro.jdbc.permissionsSql=select permission from role_permission where role_name=?

在上述配置信息中,我们定义了三个SQL语句,分别用于查询用户名对应的密码、查询用户名对应的角色名称以及查询角色名称对应的权限信息。这些SQL语句会在JdbcRealm中被使用。

在Spring Boot应用中,我们需要在配置类中注入JdbcRealm,并配置Shiro的SecurityManager和FilterChain等信息。示例如下:

@Configuration
public class ShiroConfig {
    @Bean
    public JdbcRealm jdbcRealm(DataSource dataSource) {
        JdbcRealm realm = new JdbcRealm();
        realm.setDataSource(dataSource);
        realm.setAuthenticationQuery("select password from user where username=?");
        realm.setUserRolesQuery("select role_name from user_role where username=?");
        realm.setPermissionsQuery("select permission from role_permission where role_name=?");
        return realm;
    }

    @Bean
    public DefaultWebSecurityManager securityManager(JdbcRealm jdbcRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(jdbcRealm);
        return securityManager;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);
        Map<String, String> filterChain = new LinkedHashMap<>();
        filterChain.put("/logout", "logout");
        filterChain.put("/**", "authc");
        shiroFilter.setFilterChainDefinitionMap(filterChain);
        shiroFilter.setLoginUrl("/login");
        return shiroFilter;
    }
}

在上述配置中,我们注入了JdbcRealm,并设置了SecurityManager和FilterChain等信息。filterChain.put("/**", "authc")表示所有资源都需要进行身份认证。shiroFilter.setLoginUrl("/login")设置了defaultFilterChainDefinition中authc对应的默认登陆页面,如果需要进行登陆,会跳转至该页面。

示范性案例1:简单的Web认证

以下展示一个使用JdbcRealm实现简单的Web认证的案例。

我们首先需要创建一个基本的Spring Boot应用,然后引入shiro-spring-boot-start和spring-jdbc包。

在application.properties中设置数据库连接信息和Shiro的配置信息。

在控制层中添加以下代码:

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello() {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated()) {
            return "Hello World";
        } else {
            return "请先登陆";
        }
    }

    @GetMapping("/login")
    public String login() {
        return "请先登陆";
    }
}

当请求/hello时,会进行身份认证,如果已经登陆,则返回“Hello World”,否则返回“请先登陆”。

当请求/login时,将显示登陆页面。

接下来,在启动类中添加以下代码:

@SpringBootApplication
@EnableTransactionManagement
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    // 创建一个默认用户,用于初始化数据
    @Bean
    public CommandLineRunner init(UserService userService) {
        return args -> {
            User user = new User();
            user.setUsername("admin");
            user.setPassword("admin");
            userService.createUser(user);
        };
    }
}

在上述代码中,我们通过CommandLineRunner接口创建一个默认用户,用于初始化数据。这里我们使用了UserService服务,用于将用户添加到数据库中。

接下来,我们创建UserService服务实现类:

@Service
@Transactional
public class UserServiceImpl implements UserService {
    private final UserDao userDao;

    @Autowired
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void createUser(User user) {
        userDao.createUser(user);
    }

    @Override
    public User getUserByUsername(String username) {
        return userDao.getUserByUsername(username);
    }
}

在上述代码中,我们注入了UserDao,用于将用户数据存入数据库中。

最后,我们创建UserDao实现类:

@Repository
public class UserDaoImpl implements UserDao {
    private final JdbcTemplate jdbcTemplate;

    @Autowired
    public UserDaoImpl(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public void createUser(User user) {
        String sql = "insert into user(username,password) values(?,?)";
        jdbcTemplate.update(sql, user.getUsername(), user.getPassword());
    }

    @Override
    public User getUserByUsername(String username) {
        String sql = "select password from user where username=?";
        RowMapper<User> rowMapper = (resultSet, i) -> {
            User user = new User();
            user.setUsername(username);
            user.setPassword(resultSet.getString("password"));
            return user;
        };
        List<User> userList = jdbcTemplate.query(sql, rowMapper, username);
        if (userList.isEmpty()) {
            return null;
        } else {
            return userList.get(0);
        }
    }
}

在上述代码中,我们使用JdbcTemplate实现了UserDao接口,并提供了添加用户和查询用户数据的方法。

了解了上述代码后,我们启动应用,访问 http://localhost:8080/hello ,会自动跳转至登陆页面,此时输入用户名和密码(由于上面的初始化脚本,这里我们可以使用默认的用户名“admin”和密码“admin”),登陆成功后就可以看到“Hello World”了。

示范性案例2:使用Shiro注解实现授权

以下展示一个使用Shiro注解实现授权的案例。

我们首先需要创建一个基本的Spring Boot应用,然后引入shiro-spring-boot-start和spring-jdbc包。

在application.properties中设置数据库连接信息和Shiro的配置信息。

在控制层中添加以下代码:

@RestController
public class HelloController {
    @GetMapping("/hello")
    @RequiresRoles("admin")
    public String hello() {
        return "Hello World";
    }

    @GetMapping("/login")
    public String login() {
        return "请先登陆";
    }
}

在上述代码中,我们使用@RequiresRoles注解表示需要admin角色才能访问该接口。

接下来,在启动类中添加以下代码:

@SpringBootApplication
@EnableTransactionManagement
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    // 创建一个默认用户,用于初始化数据
    @Bean
    public CommandLineRunner init(UserService userService) {
        return args -> {
            User user = new User();
            user.setUsername("admin");
            user.setPassword("admin");
            userService.createUser(user);
            UserRole userRole = new UserRole(user.getUsername(), "admin");
            userService.createUserRole(userRole);
        };
    }
}

在上述代码中,我们使用了UserService中的createUserRole方法,用于将用户添加到角色中。

接下来,我们做一些修改,在ShiroConfig中注入自定义的Relam,并设置FilterChain等信息:

@Configuration
public class ShiroConfig {
    private final ApplicationContext ac;

    @Autowired
    public ShiroConfig(ApplicationContext ac) {
        this.ac = ac;
    }

    @Bean
    public JdbcRealm jdbcRealm(DataSource dataSource) {
        JdbcRealm realm = new JdbcRealm();
        realm.setDataSource(dataSource);
        realm.setAuthenticationQuery("select password from user where username=?");
        realm.setUserRolesQuery("select role_name from user_role where username=?");
        realm.setPermissionsQuery("select permission from role_permission where role_name=?");
        return realm;
    }

    @Bean
    public DefaultWebSecurityManager securityManager(JdbcRealm jdbcRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(jdbcRealm);
        return securityManager;
    }

    @Bean
    public static DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        return new DefaultAdvisorAutoProxyCreator();
    }

    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        advisor.setAdvice(new AopAllianceAnnotationsAuthorizingMethodInterceptor());
        return advisor;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);
        Map<String, String> filterChain = new LinkedHashMap<>();
        filterChain.put("/logout", "logout");
        filterChain.put("/login", "anon");
        filterChain.put("/**", "authc");
        shiroFilter.setFilterChainDefinitionMap(filterChain);
        shiroFilter.setLoginUrl("/login");
        return shiroFilter;
    }

    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }

    @Bean
    public AnnotationMethodInvocationCachingInterceptor annotationMethodInvocationCachingInterceptor() {
        return new AnnotationMethodInvocationCachingInterceptor();
    }
}

在上述代码中,我们使用了Shiro注解实现授权,将其注入到Spring容器中。

我们需要添加UserRol实体类,并创建UserRoleDao接口和实现类如下:

public interface UserRoleDao {
    int createUserRole(UserRole userRole);
}

@Repository
public class UserRoleDaoImpl implements UserRoleDao {
    private final JdbcTemplate jdbcTemplate;

    @Autowired
    public UserRoleDaoImpl(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public int createUserRole(UserRole userRole) {
        String sql = "insert into user_role(username, role_name) values(?,?)";
        return jdbcTemplate.update(sql, userRole.getUsername(), userRole.getRoleName());
    }
}

在上述代码中,我们使用JdbcTemplate实现了UserRoleDao接口,提供了添加用户角色的方法。

了解了上述代码后,我们启动应用,访问 http://localhost:8080/hello ,会自动跳转至登陆页面,此时输入用户名和密码(由于上面的初始化脚本,这里我们可以使用默认的用户名“admin”和密码“admin”),登陆成功后就可以看到“Hello World”了。

这里需要注意,由于我们设置了UserRoleDao实现类的@Transactional注解,所以添加角色时必须提交事务,否则会报JdbcTemplate未绑定到线程的错误。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Boot在Web应用中基于JdbcRealm安全验证过程 - Python技术站

(0)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • Json字符串与Object、List、Map的互转工具类

    介绍:在Java中,经常会使用Json格式的字符串来传输数据,但是在Java程序内部我们又需要把Json字符串转换为Java对象来方便的操作数据。本文将介绍如何使用Json相关的工具类将Json字符串转换为Java对象,并将Java对象转换为Json格式的字符串。 将Json字符串转换为Java对象 当我们有一个Json格式的字符串需要转换为Java对象时,…

    Java 2023年5月26日
    00
  • SpringMVC中的Model对象用法说明

    下面是关于“SpringMVC中的Model对象用法说明”的完整攻略,包含两个示例说明。 SpringMVC中的Model对象用法说明 在SpringMVC中,Model对象是一个接口,它用于在控制器和视图之间传递数据。本文将介绍如何使用Model对象来传递数据,并提供两个示例说明。 步骤一:创建SpringMVC项目 首先,我们需要创建一个SpringMV…

    Java 2023年5月17日
    00
  • 学习Java内存模型JMM心得

    学习Java内存模型JMM心得 什么是Java内存模型 Java内存模型(Java Memory Model,JMM)是一种用于保证在多线程情况下共享变量的可见性和有序性的机制。 JMM的核心概念 Java内存模型中有三个核心概念:原子性、可见性和有序性。 原子性 原子性指的是在同一时间只有一个线程可以访问共享变量。Java中的基本数据类型,如int、lon…

    Java 2023年5月26日
    00
  • java的Guava工具包介绍

    Java的Guava工具包介绍 Guava 是什么? Guava是由谷歌(Google)发布的Java核心库的扩展,可以方便Java程序员编写更简洁、更易于维护的代码。Guava提供了很多常用的工具类和方法,例如字符串处理、集合操作、并发、IO以及基本类型等工具类。 Guava 的优点 Guava的主要优点如下: 提供了现成的API,可以帮助开发人员更快速地…

    Java 2023年5月20日
    00
  • Java 跳出递归循环问题解决办法

    Java 跳出递归循环问题通常出现在递归函数内部的某一个条件不满足时,需要跳出递归循环。 常见的解决办法有以下几种: 使用非递归实现 将递归函数转换成非递归的形式,使用栈或队列进行迭代实现。这样的好处是可以在循环中使用break或return语句来跳出循环。 示例1:阶乘的非递归实现 public static long factorial(int n) {…

    Java 2023年5月25日
    00
  • 利用Jacob将Excel转换PDF的问题汇总

    让我详细讲解一下如何利用Jacob将Excel转换为PDF。 问题背景 Jacob是一个能够在Java程序中使用微软ActiveX组件的桥接器,通过Jacob,我们可以在Java中调用Excel或其他微软Office软件的功能。本篇攻略将介绍如何使用Jacob将Excel转换为PDF。 步骤说明 1. 导入Jacob库 我们首先需要导入Jacob库,Jaco…

    Java 2023年6月15日
    00
  • SpringBoot程序预装载数据的实现方法及实践

    下面我来详细讲解一下“SpringBoot程序预装载数据的实现方法及实践”的完整攻略。 什么是SpringBoot数据预装载? SpringBoot数据预装载是指在应用程序启动时,自动加载一些初始数据并将其存储在内存中,以便在应用程序运行时使用。 SpringBoot数据预装载的实现方法 SpringBoot数据预装载的实现方法有以下两种方式: 1. 通过实…

    Java 2023年5月20日
    00
  • SQL Server 2008 连接JDBC详细图文教程

    SQL Server 2008 连接JDBC详细图文教程 1. 下载驱动程序 在连接 SQL Server 2008 数据库之前,需要先下载并安装相应的 JDBC 驱动程序。可通过以下步骤下载: 进入 Microsoft 官网下载页面; 选择适用于 Java 的 Microsoft JDBC 驱动器版本; 点击“下载”按钮开始下载。 2. 安装驱动程序 下载…

    Java 2023年6月16日
    00
合作推广
合作推广
分享本页
返回顶部