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日

相关文章

  • Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析

    针对Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析的完整攻略,可以按照以下步骤进行: 1. 确定研究目标 首先需要明确研究目标,即了解在Android系统中,进程间通信的机制及其具体实现方式。这里主要研究Binder机制在应用程序框架层的Java接口源代码分析。 2. 学习Binder机制原理 接下来需要学习Binder…

    Java 2023年5月26日
    00
  • Spring MVC注解式开发示例完整过程

    Spring MVC注解式开发示例完整过程 Spring MVC是一种基于Java的Web框架,它可以帮助我们快速开发Web应用程序。在Spring MVC中,我们可以使用注解来简化开发过程。本文将详细讲解Spring MVC注解式开发的示例过程,并提供两个示例说明。 Spring MVC注解式开发的示例过程 下面是一个Spring MVC注解式开发的示例过…

    Java 2023年5月17日
    00
  • 实现将Web应用部署到Tomcat根目录的三种方法

    当我们开发一个Web应用并且想要将其部署到Tomcat服务器的根目录时,可以采用以下三种方法: 方法一:部署WAR包到Tomcat的webapps目录下 使用Maven或Gradle等构建工具将Web应用打包成WAR包,或手动打包成WAR包。 将WAR包重命名为ROOT.war,并将其复制到Tomcat的webapps目录下。 启动Tomcat服务器,Tom…

    Java 2023年5月19日
    00
  • JavaWeb Struts文件上传功能实现详解

    JavaWeb Struts文件上传功能实现详解 简介 本文将详细讲解如何在 JavaWeb Struts 框架中实现文件上传功能,其中包括前端页面的设计和后端逻辑的实现。 设计前端页面 前端页面是实现文件上传功能的基础。在这里,我们将使用HTML和JavaScript来设计一个简单的上传页面。 示例一:HTML 代码 <!DOCTYPE html&g…

    Java 2023年5月20日
    00
  • c#桥接模式(bridge结构模式)用法实例

    C#桥接模式(Bridge结构模式)用法实例 什么是C#桥接模式? C#桥接模式,也称为Bridge模式,是一种结构性模式,它将抽象部分与实现部分分离,可以让它们相互独立地变化。这种模式属于结构型模式,它通过提供一个桥接接口,使得抽象和实现可以独立地扩展。 C#桥接模式的应用场景 C#桥接模式主要适用于以下场景: 当一个系统可能有多个角度分类(即多个维度的分…

    Java 2023年5月31日
    00
  • java实现系统捕获异常发送邮件案例

    这里为您提供java实现系统捕获异常发送邮件的完整攻略。 1. 引入依赖 首先,在你的项目中需要引入邮件发送相关的依赖,例如Apache Commons Email等。如果你使用Maven进行依赖管理,可以添加以下依赖: <dependency> <groupId>org.apache.commons</groupId> …

    Java 2023年5月27日
    00
  • SpringBoot特点之依赖管理和自动装配(实例代码)

    SpringBoot特点之依赖管理和自动装配(实例代码) 依赖管理 Spring Boot的依赖管理采用了“约定优于配置”的原则,省去了繁琐的依赖配置。Spring Boot通过Starter POMs来管理依赖,Starter POMs是一种特殊的POM文件,包含了一系列相关的依赖,我们只需要添加相应的Starter POM,即可快速地集成一些常用的依赖。…

    Java 2023年5月15日
    00
  • Spring-webflux 响应式编程的实例详解

    Spring-webflux 响应式编程的实例详解 Spring-webflux 是 Spring Framework 5.0 中引入的新特性,它提供了一种基于响应式编程模型的 Web 开发方式。本文将详细讲解 Spring-webflux 响应式编程的实例详解,包括如何创建响应式 Web 应用程序、如何使用响应式路由、如何使用响应式数据访问等。 创建响应式…

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