配置 Druid 数据源

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


数据库

需要创建 user、role、role_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. 3、vueJs基础知识03

    vue过渡(动画) 本质走的css3: transtion ,animation <div id="div1" v-show="bSign" transi ...

  2. 【Vue.js游戏机实战】- Vue.js实现九宫格水果机抽奖游戏总结

    大家好!先上图看看本次案例的整体效果. 完整版实战课程附源码:[Vue.js游戏机实战]- Vue.js实现九宫格水果机抽奖 实现思路: Vue component实现九宫格水果机组件,可以嵌套到任意 ...

  3. 腾讯云CENTOS7安装MSSQL2017

    腾讯云CENTOS7安装MSSQL2017 mkdir -p /opt/sqlserver2017cd /opt/sqlserver2017/ 下载离线包:wget https://packages. ...

  4. DELPHI开发LINUX的动态库

    DELPHI开发LINUX的动态库 WINDOWS的动态库是.dll,这个大家都知道. LINUX也有动态库,扩展名是.so,现在DELPHI也能开发LINUX的动态库哦. DELPHI对LINUX的 ...

  5. delphi 二维数组的大小和元素个数问题

    type TComplex = record Real : Single; Imag : Single; end; TKArray=array [1..2048,1..2048] of TComple ...

  6. Win10 设备管理器一个USB设备描述符请求失败解决方法

    问题:进入设备管理器,发现[通用串行总线控制器]下有一项带有黄色[!]未知USB设备(设备描述符请求失败). 或者 解决方法如下: 1.点击Windows键 +R或者(点击系统桌面左下角[开始],在开 ...

  7. 002 elasticsearch中的一些概念

    在本文中,主要是ES7中的核心概念. ElasticSearch是一个实时分布式开源全文搜索和分析引擎.它可以从RESTful网络服务接口访问,并使用无模式JSON (JavaScript对象符号)文 ...

  8. naxsi-waf-with-ui :dockerfile

    scollazo/naxsi-waf-with-ui Dockerfile - Docker Hubhttps://hub.docker.com/r/scollazo/naxsi-waf-with-u ...

  9. C++main函数命令行选项——学习笔记

    atoi字符串的数转化为整数 atof转化为小数

  10. layuiadmin(iframe)常用问题集锦

    1. 弹出窗口中传值给父层表单 table.on('tool(tableList)', function(obj){ var selected = obj.data; var layEvent = o ...