SpringBoot2.4.1整合Spring JDBC、Shiro、JSP
开发环境
SpringToolSuite4.9、JDK1.8、windows10
根据JdbcRealm规范创建数据库表
DROP TABLE IF EXISTS `permissions`;
CREATE TABLE `permissions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`url` varchar(255) DEFAULT NULL,
`type` varchar(255) DEFAULT NULL,
`pid` varchar(255) DEFAULT NULL,
`sort` varchar(255) DEFAULT NULL,
`icon` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
#
# Data for table "permissions"
#
#
# Structure for table "roles_permissions"
#
DROP TABLE IF EXISTS `roles_permissions`;
CREATE TABLE `roles_permissions` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`role_name` varchar(100) DEFAULT NULL,
`permission` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_roles_permissions` (`role_name`,`permission`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
#
# Data for table "roles_permissions"
#
INSERT INTO `roles_permissions` VALUES (1,'超级管理员','系统管理');
#
# Structure for table "user_roles"
#
DROP TABLE IF EXISTS `user_roles`;
CREATE TABLE `user_roles` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`username` varchar(100) DEFAULT NULL,
`role_name` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_user_roles` (`username`,`role_name`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
#
# Data for table "user_roles"
#
INSERT INTO `user_roles` VALUES (1,'zhang','超级管理员');
#
# Structure for table "users"
#
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`username` varchar(100) DEFAULT NULL,
`password` varchar(100) DEFAULT NULL,
`password_salt` varchar(100) DEFAULT NULL,
`createtime` datetime DEFAULT NULL,
`updatetime` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_users_username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
#
# Data for table "users"
#
INSERT INTO `users` VALUES (1,'zhang','123',NULL,NULL,NULL),(2,'admin','admin',NULL,NULL,NULL);
创建一个Spring Boot Maven项目
配置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.4.1</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>yu</groupId>
<artifactId>jdbc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>yu</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-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--Druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!--shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.1</version>
</dependency>
<!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!-- 部署tomcat,排除冲突 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- servlet依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.apache.taglibs</groupId>
<artifactId>taglibs-standard-impl</artifactId>
<version>1.2.5</version>
</dependency>
<!-- tomcat的支持 -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- 打jar需要的插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
配置application.yml
server:
port: 8080
tomcat:
uri-encoding: UTF-8
#spring:
# datasource:
# driverClassName: com.mysql.cj.jdbc.Driver
# driver-class-name: com.mysql.jdbc.Driver
# url: jdbc:mysql://127.0.0.1:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&useSSL=true&serverTimezone=UTC
# username: root
# password: root
spring:
datasource:
druid:
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&useSSL=true&serverTimezone=UTC
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
mvc:
view:
prefix: /WEB-INF/jsp/
suffix: .jsp
#打开浏览器访问:http://localhost:8080/swagger-ui.html
创建ShiroConfig
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ShiroConfig {
@Bean
public JdbcRealm getJdbcRealm(DataSource dataSource){
//JdbcRealm会自行从数据库查询用户以及权限数据(数据库的表结构要符合JdbcRealm的规范)
JdbcRealm jdbcRealm=new JdbcRealm();
jdbcRealm.setDataSource(dataSource);
//JdbcRealm默认开启认证功能,需要手动开启授权功能
jdbcRealm.setPermissionsLookupEnabled(true);
return jdbcRealm;
}
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(JdbcRealm jdbcRealm){
DefaultWebSecurityManager defaultSecurityManager=new DefaultWebSecurityManager();
defaultSecurityManager.setRealm(jdbcRealm);//SecurityManager完成校验需要realm
return defaultSecurityManager;
}
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultSecurityManager securityManager){
ShiroFilterFactoryBean filter=new ShiroFilterFactoryBean();
//过滤器是shiro执行权限的核心,进行认证和授权是需要SecurityManager的
filter.setSecurityManager(securityManager);
//设置shiro的拦截规则
Map<String,String> filterMap=new HashMap<>();
//user:使用remberme的用户可访问
//perms:对应权限可访问
//role:对应的角色才能访问
filterMap.put("/","anon");//anon表示不拦截(匿名用户可访问)
filterMap.put("/login","anon");
filterMap.put("/regist","anon");
filterMap.put("/user/login","anon");
filterMap.put("/user/regist","anon");
filterMap.put("/static/**","anon");
filterMap.put("/**","authc");//authc表示认证用户可访问
filter.setFilterChainDefinitionMap(filterMap);
filter.setLoginUrl("/login.jsp");
//设置未授权访问的页面
filter.setUnauthorizedUrl("/login.jsp");
return filter;
}
}
创建SwaggerConfig
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any()).build();
}
private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("SpringBoot API Doc")
.description("This is a restful api document of Spring Boot.")
.version("1.0")
.build();
}
}
UserController
import java.text.DateFormat;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import yu.system.entity.User;
import yu.system.service.IUserService;
@Controller
public class UserController {
@Autowired
private IUserService userService;
@RequestMapping("/")
public String view(Model model) {
return "login";
}
@RequestMapping("/index")
public String index(Model model) {
model.addAttribute("now","当前北京时间:"+ DateFormat.getDateTimeInstance().format(new Date() ));
return "index";
}
@ResponseBody
@RequestMapping(value ="/jdbc/{username}/{password}")
public String test1(@PathVariable String username,@PathVariable String password){
User u = new User();
u.setUsername(username);
u.setPassword(password);
return userService.addUser(u) + "";
}
@PostMapping(value="/save")
public Object save(@RequestBody User user) {
userService.addUser(user);
return 1;
}
@GetMapping(value="/delete")
public Object delete(@RequestParam("id") String id) {
userService.delete(id);
return 1;
}
@ResponseBody
@GetMapping(value="/findAll")
public Object findAll() {
return userService.findAll();
}
@RequestMapping("login")
public String login(String name,String password,Model model){
try{
userService.checkLogin(name,password);
System.out.println("用户:"+name+" 登陆成功时间:"+DateFormat.getDateTimeInstance().format(new Date() ));
System.out.println("用户名\t密码");
System.out.println(name+"\t"+password);
model.addAttribute("msg", "登陆成功时间:"+DateFormat.getDateTimeInstance().format(new Date() ));
return "index";
}catch (Exception e){
System.out.println("用户名\t密码");
System.out.println(name+"\t"+password);
String msg= "登录失败:\t"+ e.getMessage();
System.err.println(msg);
return "login";
}
}
}
UserService
import java.util.List;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import yu.system.dto.IUserDto;
import yu.system.entity.User;
@Service
public class UserService implements IUserService {
@Autowired
private IUserDto userDto;
@Override
public int addUser(User user) {
return userDto.addUser(user);
}
@Override
public void delete(String id) {
userDto.delete(id);
}
@Override
public List<User> findAll() {
return userDto.findAll();
}
@Override
public void checkLogin(String name, String password) {
Subject subject=SecurityUtils.getSubject();
UsernamePasswordToken token=new UsernamePasswordToken(name,password);
subject.login(token);
}
}
UserDto
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import yu.system.entity.User;
@Repository
public class UserDto implements IUserDto {
@Autowired
private final JdbcTemplate jdbcTemplate; // JdbcTemplate需实例化,写在构造方法中
public UserDto(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public int addUser(User user) {
RandomNumberGenerator gen = new SecureRandomNumberGenerator();
ByteSource salt = gen.nextBytes();
String hashedPasswordBase64 = new Sha256Hash(user.getPassword(), salt, 1024).toBase64();
user.setPassword(hashedPasswordBase64);
user.setPassword_salt(salt.getBytes());
String sql = "insert into users(username, password,password_salt,createtime) values(?,?, ?,?)";
return jdbcTemplate.update(sql,
user.getUsername(),
user.getPassword(),
user.getPassword_salt(),
DateFormat.getDateTimeInstance().format(new Date()));
}
@Override
public void delete(String id) {
String sql = "delete from users where id=?";
jdbcTemplate.update(sql, id);
}
@Override
public List<User> findAll() {
String sql = "select * from users";
return jdbcTemplate.query(sql, new BeanPropertyRowMapper(User.class));
}
}
User
package yu.system.entity;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Date;
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String username;
private String password;
private byte[] password_salt;
private Date createtime;
private Date updatetime;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getCreatetime() {
return createtime;
}
public void setCreatetime(Date createtime) {
this.createtime = createtime;
}
public Date getUpdatetime() {
return updatetime;
}
public void setUpdatetime(Date updatetime) {
this.updatetime = updatetime;
}
public byte[] getPassword_salt() {
return password_salt;
}
public void setPassword_salt(byte[] password_salt) {
this.password_salt = password_salt;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + ", password_salt="
+ Arrays.toString(password_salt) + ", createtime=" + createtime + ", updatetime=" + updatetime + "]";
}
}
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<form action="/login">
<input type="text" name="name">
<input type="password" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
${now } ${msg }
</body>
</html>
本文完