• 首先是使用的SpringBoot框架

   基础需要的pom以来如下,基础的springboot项目的创建就不一一赘述了。

        <!--spring web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--jpa 对数据库操作的框架 类似mybatis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--页面引擎 thymeleaf模板-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--mysql数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
  • 加入必须的security依赖
       <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

数据库连接配置文件

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://xx.xx.xx.xx:3306/springsecurity?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
spring.datasource.username=user
spring.datasource.password=password #设置运行时打印sql语句
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update #关闭thymeleaf缓存
spring.thymeleaf.cache=false #不用数据库认证时默认的用户名和密码
#spring.security.user.name=admin
#spring.security.user.password=1234
  • 实体类***********重要***********

  对于实体类的创建:

  1. 用户表包含权限表
  2. 用户表不包含权限表

  笔者使用的是用户表包含权限表的方式,那么不包含权限表该怎么解决呢?

    创建一个新的实体类,如SecurityUser 继承User 实现UserDetails 它包含User的内容和UserDetails的内容,对于权限的设置就不一样了

      重点注意这个方法 getAuthorities ,它来将权限交给security管理 暂时可以用Null值 在UserDetailsService中具体赋值

@Entity
public class User implements Serializable, UserDetails { private String username; private String password; private String role; public User(){} 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 String getRole() {
return role;
} public void setRole(String role) {
this.role = role;
} /**
* 指示用户的账户是否已过期。无法验证过期的账户。
* 如果用户的账户有效(即未过期),则返回true,如果不在有效就返回false
*/
@Override
public boolean isAccountNonExpired() {
return true;
} /**
* 指示用户是锁定还是解锁。无法对锁定的用户进行身份验证。
* 如果用户未被锁定,则返回true,否则返回false
*/
@Override
public boolean isAccountNonLocked() {
return true;
} /**
* 指示用户的凭证(密码)是否已过期。过期的凭证阻止身份验证
* 如果用户的凭证有效(即未过期),则返回true
* 如果不在有效(即过期),则返回false
*/
@Override
public boolean isCredentialsNonExpired() {
return true;
} /**
* 指示用户是启用还是禁用。无法对禁用的用户进行身份验证
* 如果启用了用户,则返回true,否则返回false
*/
@Override
public boolean isEnabled() {
return true;
} /**
* 得到用户的权限,如果权限表和用户表是分开的,我们需要在重新定义一个实体类实现UserDetails 并且继承于User类
* 交给security的权限,放在UserDetailService进行处理
*/
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> authorities = new ArrayList<>();
//角色必须以ROLE_开头,如果数据库没有,则需要加上 至于角色为什么必须要以ROLE_开头 笔者没有进行深究
authorities.add(new SimpleGrantedAuthority("ROLE_"+this.role));
return authorities;
}
}
  • 此处就先不谈security的config配置吧,后面会提到

     我们还没有用到数据库中的数据,在此我们需要改造UserServiceImpl类,让其实现 UserDetailsService 并重写其中的 loadUserByUsername 方法,这是数据库认证的必要流程,贴代码:

@Service
public class UserServiceImpl implements UserService, UserDetailsService {
@Autowired
UserDao userDao; /**
* 实现security认证实现的方法
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
logger.error("username:" + username);
//option这个东西请读者自行研究,此处可以直接是一个user,optional只是用于判断空值,避开空指针异常的
Optional<User> byUsername = userDao.findByUsername(username);
if (!byUsername.isPresent()) {
throw new UsernameNotFoundException("用户名不存在,请先注册后登录!");
}else{
//权限表和用户表分开************按照下面方式,如果不是,直接返回带有权限信息的User对象
//查询的权限在此处可以通过数据库查询,并且赋值
//List<GrantedAuthority> authorities=new ArrayList<>();
//authorities.add(new SimpleGrantedAuthority("ROLE_SPITTER"))
//新创建一个SecurityUser(自定义实现了UserDetails的类)
//将authorites放到该对象中,并返回出去
return byUsername.get();
}
}
}
  • 对于security的配置******************重要

  新创建一个配置类继承 WebSecurityConfigurerAdapter

  需要注意的几个方法(重写的方法):

    configure(HttpSecurity http)   :     htpp请求安全处理

    configure(AuthenticationManagerBuilder auth)    :  自定义数据库权限认证

    configure(WebSecurity web)    :    WEB安全

   

@Configuration
@EnableWebSecurity // 开启注解
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启注解 //自定义了一个springSecurity安全框架的配置类 继承WebSecurityConfigurerAdapter,重写其中的方法configure,
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserServiceImpl userService; @Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable() //接触防止跨域请求
.authorizeRequests()
.antMatchers("/toLogin","/templates/**","/logout","/toIndex").permitAll() //忽略认证的url
.anyRequest().authenticated() //其他的url都需要被认证才可以访问
.and()
.formLogin() //允许自定义表单登录
.loginPage("/toLogin") //这是action地址 不能写具体页面 确定自定义登录页 自己不需要写login方法 登录是由security提供
.loginProcessingUrl("/login") //这是html中form中action的值 必须要对应
.defaultSuccessUrl("/toIndex") //默认登录成功会跳转的controller
//关于登录失败的提示信息,请读者自行解决
.failureForwardUrl("/login-error")
.failureUrl("/login-error");
} //密码加密,最新的security必须使用密码加密
@Bean
public PasswordEncoder passwordEncoder(){
//使用BCcypt加密
return new BCryptPasswordEncoder();
} @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//从数据库读取的用户进行身份认证 实现了userDetailsService的类
auth.userDetailsService(userService)
.passwordEncoder(passwordEncoder());
} //解除对静态资源的保护
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/js/**","/templates/**");
} }
  • 接下来是Controller和页面
  • 必须要登录成功才可以访问其他的接口,没有通过认证会一直卡在login
@Controller
public class UserController {
@Autowired
UserServiceImpl userService; @RequestMapping("/toIndex")
public String index(){
return "index";
} @RequestMapping("/toLogin")
public String login(){
return "login";
}
//定义需要访问的权限
@PreAuthorize("hasAnyRole('ROLE_admin')")
@RequestMapping("/sayHello")
@ResponseBody
public String sayHello(){
return "hello";
}
//定义需要访问的权限
@PreAuthorize("hasAnyAuthority('ROLE_user')")
@RequestMapping("/sayYes")
@ResponseBody
public String sayYes(){
return "yes";
} }

  html页面

<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!--layui css-->
<link rel="stylesheet" th:href="@{js/layui-v2.5.5/layui/css/layui.css}">
<!--layui js-->
<script th:src="@{js/layui-v2.5.5/layui/layui.js}"></script>
<!--jquery-->
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<title>登录页面</title>
</head>
<body>
<!--这里请注意action的值需要与loginProcessingUrl 相对应-->
<form action="/login" method="post">
<div class="layui-form-item">
<label class="layui-form-label">输入框</label>
<div class="layui-input-inline">
<input type="text" id="username" name="username" required lay-verify="required" placeholder="请输入用户名" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">密码框</label>
<div class="layui-input-inline">
<input type="password" name="password" required lay-verify="required" placeholder="请输入密码" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn layui-btn-warm" lay-submit lay-filter="formDemo">登录</button>
</div>
</div>
</form>
</body>
</html>

第一次写博客 感觉还是有点乱,请和谐讨论,笔者也是看了很多其他的博客慢慢弄出来的,希望大家不要害怕麻烦,慢慢来,引入就不贴了,看了太多 也不知道谁是谁的

Spring Security 入门学习--数据库认证和授权的更多相关文章

  1. Spring Security + JJWT 实现 JWT 认证和授权

    关于 JJWT 的使用,可以参考之前的文章:JJWT 使用示例 一.鉴权过滤器 @Component public class JwtAuthenticationTokenFilter extends ...

  2. Spring Security OAuth2 微服务认证中心自定义授权模式扩展以及常见登录认证场景下的应用实战

    一. 前言 [APP 移动端]Spring Security OAuth2 手机短信验证码模式 [微信小程序]Spring Security OAuth2 微信授权模式 [管理系统]Spring Se ...

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

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

  4. Spring Security 入门(基本使用)

    Spring Security 入门(基本使用) 这几天看了下b站关于 spring security 的学习视频,不得不说 spring security 有点复杂,脑袋有点懵懵的,在此整理下学习内 ...

  5. SpringBoot集成Spring Security入门体验

    一.前言 Spring Security 和 Apache Shiro 都是安全框架,为Java应用程序提供身份认证和授权. 二者区别 Spring Security:重量级安全框架 Apache S ...

  6. Spring Security 解析(三) —— 个性化认证 以及 RememberMe 实现

    Spring Security 解析(三) -- 个性化认证 以及 RememberMe 实现   在学习Spring Cloud 时,遇到了授权服务oauth 相关内容时,总是一知半解,因此决定先把 ...

  7. 阶段5 3.微服务项目【学成在线】_day16 Spring Security Oauth2_05-SpringSecurityOauth2研究-搭建认证服务器

    3 Spring Security Oauth2研究 3.1 目标 本项目认证服务基于Spring Security Oauth2进行构建,并在其基础上作了一些扩展,采用JWT令牌机制,并自定 义了用 ...

  8. Spring Security 入门详解(转)

    1.Spring Security介绍 Spring Security是基于spring的应用程序提供声明式安全保护的安全性框架,它提供了完整的安全性解决方案,能够在web请求级别和方法调用级别 处理 ...

  9. Spring Security 入门详解

    序:本文主要参考 spring实战 对里面的知识做一个梳理 1.Spring Security介绍 Spring Security是基于spring的应用程序提供声明式安全保护的安全性框架,它提供了完 ...

随机推荐

  1. Numpy random函数

    import numpy as np # 生成一个随机数组 np.random.randint(0,6,3) # array([1, 1, 3]) # 生成一个随机数组(二维数组) np.random ...

  2. POJ 2443 Set Operation 题解

    本文同时发布于 博客园 洛谷博客 题目链接 题目分析 给你n个集合,每个集合里面都有可能会重复的数字 q个询问,每次询问两个数是否会在同一集合内 $n<=1000$ $q<=200000$ ...

  3. [转] 总结了N个真实线上故障

    以下文章来源于架构师进阶之路 ,作者二马读书 1. JVM频繁FULL GC快速排查 在分享此案例前,先聊聊哪些场景会导致频繁Full GC: 内存泄漏(代码有问题,对象引用没及时释放,导致对象不能及 ...

  4. 通过MyBatis操作数据库

    MyBatis是一款优秀的持久层框架,同样也是做OR Mapping的.与JPA不同,MyBatis里面需要我们自己来定制sql. MyBatis和JPA的选择 其实如果业务比较操作比较简单使用JPA ...

  5. wps 2011 破解版软件

    今天换了一台新电脑. wps 都没有 系统的太过忍受不了 整了一天终于是找到了一个合适安装的 想要的邮件发给我  673658917@qq.com

  6. c++萌新到大牛,要看哪些书?

    基础语法 <c++primer> 语法进阶 <c++primer plus> 专为c++编著.支持c++14国际标准. 数据结构和算法 <大话数据结构> 编程规范 ...

  7. C++输出错误信息perror、strerror以及全局变量errno

    头文件:#include<stdio.h>函数:perror.strerror,全局变量:errno.使用方法: FILE *fp; if((fp = fopen("test.t ...

  8. C#LeetCode刷题之#771-宝石与石头(Jewels and Stones)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3812 访问. 给定字符串J 代表石头中宝石的类型,和字符串 S代 ...

  9. vue.js中 v-for,v-on,v-model,结合应用案例---记事本

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  10. CompletableFuture异步线程

    1.线程池七大参数介绍 (1)corePoolSize:线程池中常驻核心线程数 (2)maximumPoolSize:线程池能够容纳同时执行的最大线程数,此值必须大于等于1 (3)keepAliveT ...