本文是原创的,主要讲如何用Spring 框架连接Oracle11g。但是最终的目的是研究如何实现权限方面的控制和管理,因此表是按照spring referece中安全参考中的创建用户和权限的数据库脚本来做的。
前期准备工作
安装Oracle11g
根据spring referece中安全参考中的:https://docs.spring.io/spring-security/site/docs/5.3.3.RELEASE/reference/html5/#servlet-authentication-jdbc 其中的10.10.5. JDBC Authentication
这里面有以后需要用到的用户表和权限表。原文是:
Example 62. Default User Schema for Oracle Databases
CREATE TABLE USERS (
USERNAME NVARCHAR2(128) PRIMARY KEY,
PASSWORD NVARCHAR2(128) NOT NULL,
ENABLED CHAR(1) CHECK (ENABLED IN ('Y','N') ) NOT NULL
);
CREATE TABLE AUTHORITIES (
USERNAME NVARCHAR2(128) NOT NULL,
AUTHORITY NVARCHAR2(128) NOT NULL
);
ALTER TABLE AUTHORITIES ADD CONSTRAINT AUTHORITIES_UNIQUE UNIQUE (USERNAME, AUTHORITY);
ALTER TABLE AUTHORITIES ADD CONSTRAINT AUTHORITIES_FK1 FOREIGN KEY (USERNAME) REFERENCES USERS (USERNAME) ENABLE;
在Oracle SqlPlus中 输入以上代码就可以创建表users 和表 authorities ,并添加了唯一约束和外键约束。
然后为了方面我们看程序的效果,可以添加一些数据进入这个用户表,可以运行以下代码:
insert into USERS (USERNAME,PASSWORD,ENABLED)values('tom','Free212','Y' );
insert into USERS (USERNAME,PASSWORD,ENABLED)values('jerry','Free123','Y' );
这样用户表里面就有数据了。
下面是和程序代码有关的,大概过程就是建立应用程序,用JDBC连接这个库,然后访问里面的数据,显示到HTML页面中去。
套路和SpringGuide中的各个guide很像了,懂了的可以大概看看,都是一样一样的。只不过因为我这是连接的Oracle11g,官方对Oracle的支持已经是最新的了,所以依赖关系处要做一点事情才行。
一步一步来吧。
Starting with Spring Initializr
创建应用程序,Artifact:jdbcoracle11gTest其他的不用变,版本选择2.3.6,java的版本选择8,右侧依赖关系选择如下图(本例子中真正有用处的就只是Spring Web 、JDBCAPI和OracleDriver):
点击Generate,生成后会自动下载该项目压缩包,解压缩后存到本地。此时的目录结构如下图所示:
用你的IDE环境SpringToolSuite4.exe -打开这个项目。
我们会看到这个Pom.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>jdbcoracle11gTest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jdbcoracle11gTest</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
这个文件里面,我们主要关注和Oracle Driver有关的那段,需要修改一下。
原来是:
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<scope>runtime</scope>
</dependency>
修改后是:
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.1.0</version>
</dependency>
这个地方 <scope>runtime</scope>这个是一个范围标签,为了简单,我在修改后的文件中没有这个,你们可以试试,加上影响不影响,就是起了一个规定什么阶段用这个包的作用。
Oracle11g的jar文件是ojdbc6.jar ,如果安装了oracle,这个文件位于:D:\app\arcgi\product\11.2.0\dbhome_1\jdbc\lib(就是安装Oracle的目录下了),有ojdbc5,和ojdbc6,我用的是ojdebc6,你们可以试试用ojdbc5.
修改后的pom.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>jdbcoracle11gTest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jdbcoracle11gTest</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.1.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
这个时候你会发现这个pom文件有错误,原因就是maven*库是有ojdbc8的,你的本地库配置的也是ojdbc8,没有ojdbc6,需要手工把这个ojdbc6加到你的本地库中去,命令如下(windows中进入cmd然后输入即可):
mvn install:install-file -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=11.2.0.1.0 -Dpackaging=jar -Dfile=D:\app\arcgi\product\11.2.0\dbhome_1\jdbc\lib\ojdbc6.jar
之后,你可以到你的本地库去看看,文件目录和com.oracle 是由一个目录关系的,如图:
打开ojdbc6是这样的:
这个地方如果由强迫症的可以写的规范一点,像官方那样写。无所谓了,maven能找到就行了。
到此处我们完成了开发环境的配置,下面就是写一点代码,测试一下我们到底能不能连接到Oracle11g。
参考这个文章:https://spring.io/guides/gs/relational-data-access/
这个文章中的
Create a Customer
Object
package com.example.relationaldataaccess;
public class Customer {
private long id;
private String firstName, lastName;
public Customer(long id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public String toString() {
return String.format(
"Customer[id=%d, firstName='%s', lastName='%s']",
id, firstName, lastName);
}
// getters & setters omitted for brevity
}
这个文件需要修改一下,以适应我们数据库里面的Users表,第一句包的语句也需要改一下。
改为如下的文件:
package com.example.relationaldataaccess;
public class Customer {
private long id;
private String firstName, lastName;
public Customer(long id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
// getters & setters omitted for brevity
}
添加一个Controller,这样网页上就可以调用这个Controller,就可以看到结果了。
package com.example.jdbcoracle11gTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class OneController {
@Autowired
private JdbcTemplate jdbcTemplate;
@RequestMapping("/")
@ResponseBody
public String index(){
String sql = "insert into users (username,password,enabled) values ('junwei','shabi666','Y')";
jdbcTemplate.execute(sql);
System.out.println("执行完成");
return "hello spring boot";
}
}
保存一下,然后IDE中 :Run as Spring Boot App
每次运行记得修改一下插入的用户名和密码,要不就报错。运行一次,就插入一条语句,然后可以去SQLPLUS中做个查询看看。
我运行了一下,还不行,报错。
错误如下:
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
Action:
Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).
百度了一下发现是未作配置数据源的工作,这个配置均在application.properties文件中完成,找到application.properties文件,
找到后输入如下配置项:
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
spring.datasource.username=system
spring.datasource.password=Free999
server.port=7070
用户名和密码需要自己改一下你自己的哦,尤其是密码别和我一样啊。端口可以改为8080,9090 都可以了。
再次运行,
发现居然弹出了默认的登录页面,这个我们也没有做什么配置,因此还是有问题 。这个地方需要再配置一下,添加 一个新的类,来做安全控制。
添加WebSecurityConfig类,它是做安全控制的。
代码如下:
package com.example.jdbcoracle11gTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
@Bean
@Override
public UserDetailsService userDetailsService() {
UserDetails user =
User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
语句 .antMatchers("/", "/home").permitAll()的意思是说 任何人都可以访问这两个页面。
然后,我们的index()函数就运行了,插入了一条数据返回了,return "hello spring boot";
此时可以先关闭这个工程,然后再打开,再运行。如果没有啥问题,浏览器中输入localhost:7070/
如下图
去数据库看看,sqlplus中新的记录已经添加
我们连接上了Oracle,更新了数据,成功了。
下一步是研究Spring 的安全机制,实现基于JDBC Oracle的权限控制。