• 首先是使用的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. PHP zip_entry_compressedsize() 函数

    定义和用法 zip_entry_compressedsize() 函数返回 zip 档案项目的压缩文件尺寸.高佣联盟 www.cgewang.com 语法 zip_entry_compressedsi ...

  2. 7.1 NOI模拟赛 凸包套凸包 floyd 计算几何

    计算几何之所以难学 就是因为太抽象了 不够直观 而且情况很多 很繁琐 甚至有一些东西不清不楚.. 这道题注意到题目中的描述 一个鸽子在两个点所连直线上也算. 通过看题解 发现这个地方并非直线而是线段 ...

  3. PAM学习笔记

    想了想 还是要先把字符串的东西先都学完告一段落了再说 时间不多了 加油~. PAM 回文自动机 比SAM简单到不知道哪里去了. 回文自动机和其他自动机一样有字符集 有状态 有转移. 一个字符串的回文自 ...

  4. Spring Cloud Data Flow初体验,以Local模式运行

    1 前言 欢迎访问南瓜慢说 www.pkslow.com获取更多精彩文章! Spring Cloud Data Flow是什么,虽然已经出现一段时间了,但想必很多人不知道,因为在项目中很少有人用.不仅 ...

  5. 数位DP 学习笔记

    前言:鸣谢https://www.luogu.com.cn/blog/virus2017/shuweidp.感谢大佬orz ----------------------------- [引入] 首先要 ...

  6. 【HEOI2015】公约数数列 题解(分块)

    前言:毒瘤数据结构题,半个下午都在搞它了…… --------------------------- 题目链接 题目大意:给定一个长度为$n$的序列,有两种操作:1.把$a_x$的值改成$y$.2.求 ...

  7. 无法加载文件或程序集“System.Net.Http,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a”

    原因是:System.Net.Http.dll 使用了net4.6的版本的.而System.Net.Http.Formatting.dll使用了4.5的版本. 解决方案:将webconfig文件下的n ...

  8. Python-关于正则表达式的总结

    什么是正则表达式? 正则表达式(regular expression)描述了一种字符串匹配的模式(pattern),用于字符串的 匹配 和 提取 等操作.正则表达式在所有编程语言中都是通用的. 很多人 ...

  9. CSS内容布局

    网页是由不同内容块构成的:标题.段落.链接.列表.图片.视频,等等. 1.定位 定位并不适合总体布局,因为它会把元素拉出页面的正常流. 元素的初始定位方式为静态定位(static),即块级元素垂直堆叠 ...

  10. javascript函数的笔记

    1.函数的概念     封装一段可以被重复调用执行的代码块来实现大量代码的重复使用     2.函数的使用分为两步:声明函数 和 调用函数     3.声明函数的关键字全部是小写     4.函数名一 ...