配置 Druid 数据源

配置 Druid 数据源,看下这篇博客,至于后面的添加监控那些就不用看了,仅仅看如何整合的 ;


数据库

需要创建 userrolerole_user 表。建表语句我已经写好了:

CREATE TABLE IF NOT EXISTS USER (
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
name VARCHAR(10),
password VARCHAR(50)
)
CHARSET utf8; CREATE TABLE IF NOT EXISTS ROLE (
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
name VARCHAR(10)
)
CHARSET utf8; CREATE TABLE IF NOT EXISTS ROLE_USER (
user_id INT,
role_id INT
)
CHARSET utf8; # 防止项目启动,出现重复插入而报错
INSERT INTO `ROLE` (`id`, `name`) SELECT
'1',
'ROLE_ADMIN'
FROM dual
WHERE NOT exists(SELECT id
FROM `ROLE`
WHERE id = '1');
INSERT INTO `ROLE` (`id`, `name`) SELECT
'2',
'ROLE_USER'
FROM dual
WHERE NOT exists(SELECT id
FROM `ROLE`
WHERE id = '2'); INSERT INTO `USER` (`id`, `password`, `name`) SELECT
'1',
'root',
'root'
FROM dual
WHERE NOT exists(SELECT id
FROM `USER`
WHERE id = '1');
INSERT INTO `USER` (`id`, `password`, `name`) SELECT
'2',
'yiaz',
'yiaz'
FROM dual
WHERE NOT exists(SELECT id
FROM `USER`
WHERE id = '2'); INSERT INTO `ROLE_USER` (`user_id`, `role_id`) SELECT
'1',
'1'
FROM dual
WHERE NOT exists(SELECT user_id
FROM `ROLE_USER`
WHERE user_id = '1');
INSERT INTO `ROLE_USER` (`user_id`, `role_id`) SELECT
'2',
'2'
FROM dual
WHERE NOT exists(SELECT user_id
FROM `ROLE_USER`
WHERE user_id = '2');

执行下即可。或者自己写,也行;


Mapper 文件


public interface LoginMapper { @Select("select * from user where name = #{name}")
MyUser loadUserByUsername(String name); @Select("SELECT role.`name` FROM role WHERE role.id in (SELECT role_id FROM " +
" role_user as r_s JOIN `user` as u ON r_s.user_id = u.id and u.id = #{id})")
List<Role> findRoleByUserId(int id);
}

自定义 UserDetailsService

UserDetailsService 的主要作用是,获取数据库里面的信息,然后封装成对象,我们既然需要从数据库中读取用户,那么我们就需要实现自己的 UserDetailsService ,按照我们的逻辑完成从数据库中获取信息;

/**
* 主要是封装从数据库获取的用户信息
*
* @author yiaz
* @date 2019年3月19日10:50:58
*/
@Component
public class UserDetailServiceImpl implements UserDetailsService { // demo 不想写 service层,直接 dao 层穿透到 controller 层
@Autowired
private LoginMapper loginMapper; @Override
public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
// 根据用户名查询数据库,查到对应的用户
MyUser myUser = loginMapper.loadUserByUsername(name); // ... 做一些异常处理,没有找到用户之类的
if(myUser == null){
throw new UsernameNotFoundException("用户不存在") ;
} // 根据用户ID,查询用户的角色
List<Role> roles = loginMapper.findRoleByUserId(myUser.getId());
// 添加角色
List<GrantedAuthority> authorities = new ArrayList<>();
for (int i = 0; i < roles.size(); i++) {
authorities.add(new SimpleGrantedAuthority(roles.get(i).getName()));
}
// 构建 Security 的 User 对象
User user = new User(myUser.getName(), myUser.getPassword(), authorities); return user;
}
}

自定义登陆校验器 AuthenticationProvider

我们既然不用 security 来帮我们检验,就要实现自己的校验逻辑,实现自己的 AuthenticationProvider 类,完成校验 ;

BCryptPasswordEncoder 是完成加盐MD5 的一个类,很棒,思路和笔者许久之前想到的差不多。不需要我们去管理盐值的问题,也不需要在数据库里面进行存储了;

/**
* 完成校验工作
*/
@Component
public class MyAuthenticationProvider implements AuthenticationProvider {
@Autowired
private UserDetailServiceImpl userDetailService; /**
* 进行身份认证
*
* @param authentication
* @return
* @throws AuthenticationException
*/
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException { // 获取用户输入的用户名和密码
String username = authentication.getName();
String password = authentication.getCredentials().toString();
// 获取封装用户信息的对象
UserDetails userDetails = userDetailService.loadUserByUsername(username);
// 进行密码的比对
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
boolean flag = bCryptPasswordEncoder.matches(password, userDetails.getPassword());
// 校验通过
if (flag){
// 将权限信息也封装进去
return new UsernamePasswordAuthenticationToken(userDetails,password,userDetails.getAuthorities());
} // 验证失败返回 null
return null;
} /**
* 这个方法 确保返回 true 即可,
*
* @param aClass
* @return
*/
@Override
public boolean supports(Class<?> aClass) {
return true;
}
}

配置 security

将之前的 WebSecurityConfig 类中的 WebSecurityConfigurerAdapter 做如下修改:


/**
* security 配置
* @param myAuthenticationProvider
* @return
*/ @Autowired
@Bean
public WebSecurityConfigurerAdapter webSecurityConfigurerAdapter(MyAuthenticationProvider myAuthenticationProvider) {
/**
* 配置对哪些路径进行拦截,如果方法里面什么都不写,则不拦截任何路径;
* <p>
* 如果,使用 super.configure(http),父类的方法:
* ((HttpSecurity)((HttpSecurity)((AuthorizedUrl)http.authorizeRequests().anyRequest()).authenticated().and()).formLogin().and()).httpBasic();
* <p>
* 我们自定义下拦截规则,表单等一系列规则;
*/
return new WebSecurityConfigurerAdapter() {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
// 放行登录
.antMatchers("/login/**").permitAll()
.anyRequest().authenticated()
.and()
// 开启表单认证
.formLogin()
// 地址写的是 映射的路径
.loginPage("/login.html")
// 必须添加
.loginProcessingUrl("/login")
.permitAll()
// 第二个参数,如果不写成true,则默认登录成功以后,访问之前被拦截的页面,而非去我们规定的页面
.defaultSuccessUrl("/index.html", true)
.and() .logout()
.logoutUrl("/logout")
.and()
.csrf()
.disable()
.httpBasic(); } /**
* 配置自定义校验规则,密码编码,使用我们自定义的校验器
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(myAuthenticationProvider);
} };
}

其中 loginProcessingUrl("/login") 必须写上,否则会报 405 错误 ,其中后面的参数值,写成,你自定义表单的提交地址;


后记

这样就完成了,也不难,就是有点坑,浪费了我一天时间,之前没写上 loginProcessingUrl("/login") 大家也没提到这个问题,导致一直 405 ,如果你也遇到 405 ,兴许你花了2分钟看完,就搞定了!

其实即使我们自定义了检验规则,其实我们也没有完全接手 security ,只是在其运行期间,参与了一个环节,给它一个我们自定义的检验器,让它使用我们的检验器;

(三)spring Security 从数据库中检索用户名和密码的更多相关文章

  1. spring security进阶 使用数据库中的账户和密码认证

    目录 spring security 使用数据库中的账户和密码认证 一.原理分析 二.代码实现 1.新建一个javaWeb工程 2.用户认证的实现 3.测试 三.总结 spring security ...

  2. Spring Security使用数据库数据完成认证--练气后期2

    写在前面 没错,这篇文章还是练气后期!但作者我相信筑基指日可待! 在前一篇文章当中,我们简单地分析了一下Spring Security的认证流程,知道了如果想要实现对自己用户数据(账户.角色.权限)的 ...

  3. Spring Security 3.1 中功能强大的加密工具 PasswordEncoder

    Spring Security 3.1 中功能强大的加密工具 PasswordEncoder 博客分类: security spring springsecurity  好吧,这种加密机制很复杂,还是 ...

  4. git 中添加用户名和密码

    git 中添加用户名和密码:https://blog.csdn.net/qq_28602957/article/details/52154384 在使用git时,如果用的是HTTPS的方式,则每次提交 ...

  5. spring security结合数据库验证用户-XML配置方式

    之前的用户信息我们都是使用的内存用户,测试例子可以,实际中使用肯定不行,需要结合数据库进行验证用户.这就是本节的重点: 项目目录如下:  在之前的项目中的依赖中添加两个依赖: <dependen ...

  6. spring security使用数据库资源

    国内对权限系统的基本要求是将用户权限和被保护资源都放在数据库里进行管理,在这点上Spring Security并没有给出官方的解决方案,为此我们需要对Spring Security进行扩展.. 数据库 ...

  7. spring security使用数据库验证的逻辑处理

    前面做了多个示例,包括使用jdbc和hibernate两种方式访问数据库获取用户信息和权限信息,其中一些关键步骤如下:   我们在SecurityConfig中配置覆盖configure方法时候,可以 ...

  8. spring boot系列--spring security (基于数据库)登录和权限控制

    先说一下AuthConfig.java Spring Security的主要配置文件之一 AuthConfig 1 @Configuration 2 @EnableWebSecurity 3 publ ...

  9. Spring Security 使用数据库用户进行认证

    本文参考或摘录自:http://haohaoxuexi.iteye.com/blog/2157769 本文使用Spring Security自带的方式连接数据库对用户进行认证. 1.Spring Se ...

随机推荐

  1. python3 枚举定义和使用

    定义 在某些情况下,一个类的对象是有限且固定的,比如季节类,它只有 4 个对象:再比如行星类,目前只有 8 个对象.这种实例有限且固定的类,在 Python 中被称为枚举类.程序有两种方式来定义枚举类 ...

  2. 怎么用switchhost

    第一步:打开exe, 第二部:在 My hosts 里面直接添加路径 106.75.131.183 npm.kuaizitech.cn 第三部 :打开my hosts 保护好眼睛,早睡早起,多运动,k ...

  3. python反射hasattr getattr setattr delattr

    反射 : 是用字符串类型的名字 去操作 变量 相比于用eval('print(name)') 留有 安全隐患 反射 就没有安全问题 hasattr 语法: hasattr(object, name)o ...

  4. centos 普通用户 和 root 相互切换方法

    root 用户切换为普通用户 :用 login -f username (加 -f 不用输入密码)例如普通用户的用户名为hadoop,这里就是 login -f hadoop 普通用户切换为root用 ...

  5. session设置存活时间的三种方式

    在web容器中设置(此处以tomcat为例)在tomcat-5.0.28\conf\web.xml中设置,以下是tomcat 5.0中的默认配置: [html] view plain copy < ...

  6. 对实体 "useSSL" 的引用必须以 ';' 分隔符结尾。 Nested exception: 对实体 "useSSL" 的引用必须以 ';' 分隔符结尾

    今天在定义数据源的时候,在配置context.xml文件时,连接mysql数据库的url一行发生错误,报错:“对实体 "useSSL" 的引用必须以 ';' 分隔符结尾”.以下是我 ...

  7. layer.msg 弹出不同的效果的样式

    icon 1到6的不同效果 layer.msg(,time:, shift: });//一个勾 layer.msg(,time:, shift: });//一个叉 layer.msg(,time:, ...

  8. 免费好用的SSH手机客户端

    简单说一些,SSH 为 Secure Shell 的缩写,由 IETF 的网络小组(Network Working Group)所制定,SSH 为建立在应用层基础上的安全协议.SSH 是目前较可靠,专 ...

  9. JS 数字相加出现多个小数的问题

    今天在页面上用到了js进行小数相加119.01+0.01,结果大家都知道应该是:119.02的,然而结果是119..0200000…. ,莫名其妙的,还以为是我写的程序有问题,后来查了下才知道这是ja ...

  10. 提供Web相关的个工具类

    package com.opslab.util.web; import com.opslab.util.ConvertUtil;import com.opslab.util.StringUtil; i ...