• 首先是使用的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. 2019 HL SC day4

    自闭场本来 以为 顶多一些不太会 结果发现 一堆不太会 . 树状数组  感觉 好久没看 了有点遗忘 不过还好 现在我来了.莅临之神将会消灭一切知识点哦. 今天说点不一样东西 树状数组 hh 很有用的东 ...

  2. 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用

    一.什么是 RestTemplate? RestTemplate是执行HTTP请求的同步阻塞式的客户端,它在HTTP客户端库(例如JDK HttpURLConnection,Apache HttpCo ...

  3. 【CF115E】Linear Kingdom Races 题解(线段树优化DP)

    前言:前辈讲课时设的状态还是有些繁琐,感觉题解设的状态更简洁. -------------- 题目链接 题目大意:给定$n$条道路和$m$场比赛,每个道路修建需要$c_i$,每场比赛需要使用$[l_i ...

  4. 云服务器远程连接mysql数据库

    首先需要在云服务器上,下载安装好mysql与Navicat. mysql下载好以后,打开云端的开始,找到mysql的命令窗,进入输入自己的mysql密码,稍等片刻进入mysql数据库 进入之后输入下列 ...

  5. Redis教程——检视阅读

    Redis教程--检视阅读 参考 Redis教程--菜鸟--蓝本--3.2.100 Redis教程--w3c--3.2.100 Redis教程--w3c--Redis开发运维实践指南 Redis教程- ...

  6. FPN和他的子孙们

    FPN 方框里表示top down里每层有两个卷积操作  PAN:添加一个 bottom up线 NAS-FPN:基于搜索结构的FPN  Fully-conencted FPN:全连接的FPN  Si ...

  7. web新手第二周知识汇总

    这周学习了盒模型以及一些定位的知识,现在简单做下汇总 盒模型组成部分: ie浏览器默认值是border-box content(内容盒)蓝色 padding(内容和边框的距离 绿色 填充盒包含内容)b ...

  8. C#LeetCode刷题之#112-路径总和​​​​​​​(Path Sum)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4078 访问. 给定一个二叉树和一个目标和,判断该树中是否存在根节 ...

  9. C#LeetCode刷题-字符串

    字符串篇 # 题名 刷题 通过率 难度 3 无重复字符的最长子串   24.6% 中等 5 最长回文子串   22.4% 中等 6 Z字形变换   35.8% 中等 8 字符串转整数 (atoi)   ...

  10. 用它5分钟以后,我放弃用了四年的 Flask

    有一个非常简单的需求:编写一个 HTTP接口,使用 POST 方式发送一个 JSON 字符串,接口里面读取发送上来的参数,对其中某个参数进行处理,并返回. 如果我们使用 Flask 来开发这个接口,那 ...