下面我来详细讲解“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技术站