一、Druid配置:
1、yaml配置:
spring:
datasource:
# 基本属性
name: dev
url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai&characterEncoding=utf-8
username: root
password: 123456
# 可以不配置,根据url自动识别,建议配置
driver-class-name: com.mysql.jdbc.Driver
###################以下为druid增加的配置###########################
type: com.alibaba.druid.pool.DruidDataSource
# 初始化连接池个数
initialSize: 5
# 最小连接池个数——》已经不再使用,配置了也没效果
minIdle: 2
# 最大连接池个数
maxActive: 20
# 配置获取连接等待超时的时间,单位毫秒,缺省启用公平锁,并发效率会有所下降
maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 用来检测连接是否有效的sql,要求是一个查询语句。
# 如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用
validationQuery: SELECT 1 FROM DUAL
# 建议配置为true,不影响性能,并且保证安全性。
# 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
testWhileIdle: true
# 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
testOnBorrow: false
# 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
testOnReturn: false
# 打开PSCache,并且指定每个连接上PSCache的大小
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
# 通过别名的方式配置扩展插件,多个英文逗号分隔,常用的插件有:
# 监控统计用的filter:stat
# 日志用的filter:log4j
# 防御sql注入的filter:wall
filters: stat,wall,log4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 合并多个DruidDataSource的监控数据
useGlobalDataSourceStat: true
2、配置类
@Controller
public class Druiconfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druidDatasource(){
return new DruidDataSource();
}
/**
* 主要实现WEB监控的配置处理
*/
@Bean
public ServletRegistrationBean druidServlet() {
// 现在要进行druid监控的配置处理操作
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(
new StatViewServlet(), "/druid/*");
// 白名单,多个用逗号分割, 如果allow没有配置或者为空,则允许所有访问
servletRegistrationBean.addInitParameter("allow", "127.0.0.1,172.29.32.54");
// 黑名单,多个用逗号分割 (共同存在时,deny优先于allow)
servletRegistrationBean.addInitParameter("deny", "192.168.1.110");
// 控制台管理用户名
servletRegistrationBean.addInitParameter("loginUsername", "admin");
// 控制台管理密码
servletRegistrationBean.addInitParameter("loginPassword", "123456");
// 是否可以重置数据源,禁用HTML页面上的“Reset All”功能
servletRegistrationBean.addInitParameter("resetEnable", "false");
return servletRegistrationBean ;
}
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean() ;
filterRegistrationBean.setFilter(new WebStatFilter());
//所有请求进行监控处理
filterRegistrationBean.addUrlPatterns("/*");
//添加不需要忽略的格式信息
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.css,/druid/*");
return filterRegistrationBean ;
}
}
二、shiro配置类
1、ShiroConfig类
@Configuration
public class ShiroConfig {
//3 shiroFilterFactoryBean3
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean();
// 过滤器配置
bean.setSecurityManager(defaultWebSecurityManager);
// 添加shiro的内置过滤器
/*
anon无需认证
authc必须认证才能访问
user必须拥有记住我功能才能使用
perm是拥有某个资源的权限才能使用
role 拥有某个角色才能使用
*/
//拦截
Map<String, String> filterChainDefinitionMap=new LinkedHashMap<>();
// 设置授权 访问/add 必须有user:add的权利
filterChainDefinitionMap.put("/add","perms[user:add]");
// 所有人都可访问
// filterChainDefinitionMap.put("/add","anon");
// 未授权页面
bean.setUnauthorizedUrl("/unauth");
// 要认证了才能访问(spring-security有自定义的login.html页面,而Shiro没有,需要我们自己配置)
filterChainDefinitionMap.put("/updat","authc");
bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
// 设置登录的请求
bean.setLoginUrl("/tologin");
return bean;
}
//2 DefaultwebSecurityManager2
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
securityManager.setRealm(userRealm);
System.out.println(securityManager);
return securityManager;
}
// 1 realm
@Bean(name = "userRealm")
public UserRealm userRealm(){
return new UserRealm();
}
//整合thymelaef-shiro
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
}
2、UserRelm类(授权和认证)
public class UserRealm extends AuthorizingRealm {
@Autowired
CustomerService customerService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
System.out.println("执行了---->授权:doGetAuthorizationInfo");
//拿到当前登录的对象
Subject subject=SecurityUtils.getSubject();
// 从授权中拿值,n拿到customer对象
Customer customer = (Customer) subject.getPrincipal();
String username=customer.getUsername();
//授予权限
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
// 所有的用户都有这个user:add的权限(登录才有)
if (username.equals("2")){
info.addStringPermission("user:add");
}
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("执行了————>认证:doGetAuthenticationInfo");
// 用户名,密码 数据中取
// String name ="root";
// String password="123456";
UsernamePasswordToken usernameToken = (UsernamePasswordToken) token;
Customer customer=customerService.queryByName(usernameToken.getUsername());
System.out.println(customer.toString());
String name=customer.getUsername();
String password=customer.getPhone();
if (!usernameToken.getUsername().equals(name)){
return null;//抛出异常:用户名不存在
}
Subject subject=SecurityUtils.getSubject();
Session session = subject.getSession();
session.setAttribute("result2",customer);
// 密码认证(存的值,密码,名称)
return new SimpleAuthenticationInfo(customer,password,"");
}
}
三、控制层
@RequestMapping("/login")
public String login(String username,String password,Model model){
//获取当前的用户
System.out.println(username+password);
Subject subject= SecurityUtils.getSubject();
// 获取封装当前用户
UsernamePasswordToken token=new UsernamePasswordToken(username,password);
token.setRememberMe(false);//设置记住我功能
// 捕获异常
try {
subject.login(token);
return "index";
} catch (UnknownAccountException uae) {
model.addAttribute("msg2","用户名不存在");
return "login";
} catch (IncorrectCredentialsException ice) {
model.addAttribute("msg2","密码不存在");
return "login";
}
}
四、html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>认证登录页</title>
</head>
<body>
<p th:text="${msg2}"></p>
<form th:action="@{/login}">
<p>用户名:<input type="text" name="username"></p>
<p>用户名:<input type="password" name="password"></p>
<p><input type="submit"></p>
</form>
</body>
</html>
Github上的例子
https://github.com/YAH919098892/shiro-thymeleaf-druid.git