1、功能实现

创建内存用户,进行登录
访问权限接口

2、security01 子工程

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.yzm</groupId><artifactId>security</artifactId><version>0.0.1-SNAPSHOT</version><relativePath>../pom.xml</relativePath> <!-- lookup parent from repository --></parent><artifactId>security01</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>security01</name><description>Demo project for Spring Boot</description><dependencies><dependency><groupId>com.yzm</groupId><artifactId>common</artifactId><version>0.0.1-SNAPSHOT</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

由于还没有用到数据库,启动类 exclude 数据库自动配置,以免启动报错

package com.yzm.security01;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class Security01Application {public static void main(String[] args) {SpringApplication.run(Security01Application.class, args);}
}

3、SecurityConfig 配置类

package com.yzm.security01.config;import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;@Slf4j
@Configuration
@EnableWebSecurity // 开启 Security 服务
public class SecurityConfig extends WebSecurityConfigurerAdapter {/*** 密码编码器* passwordEncoder.encode是用来加密的,passwordEncoder.matches是用来解密的*/@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}/*** 配置用户,这里是创建内存用户*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {// 从内存创建用户auth.inMemoryAuthentication().withUser("admin").password(passwordEncoder().encode("123456"))// 基于内存创建的用户不能同时使用roles和authorities,如果同时使用只有后面的生效,这个坑.roles("ADMIN", "USER")//.authorities("select", "delete").and().withUser("yzm").password(passwordEncoder().encode("123456")).roles("USER")//.authorities("select");}/*** http安全配置*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http// 关闭CSRF跨域.csrf().disable()// 默认登录.formLogin().permitAll().and()// 退出登录.logout().permitAll().and()// 访问路径URL的授权策略,如注册、登录免登录认证等.authorizeRequests().antMatchers("/home", "/").permitAll() //指定url放行.antMatchers("/user/**").hasAnyRole("ADMIN", "USER") // 需要角色(二选一).antMatchers("/admin/**").hasRole("ADMIN") // 需要角色.anyRequest().authenticated() //其他任何请求都需要身份认证.and();}
}

4、访问接口

package com.yzm.security01.controller;import com.alibaba.fastjson.JSONObject;
import com.yzm.common.entity.HttpResult;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
public class HomeController {@GetMapping(value = {"/", "/home"})public Object home() {return "home";}@GetMapping("/hello")@ResponseBodypublic Object hello() {return "hello";}// 通过authentication或userDetails获取当前登录用户信息+@GetMapping(value = {"/user", "/admin"})@ResponseBodypublic String info(Authentication authentication, @AuthenticationPrincipal UserDetails userDetails) {System.out.println("authentication :");System.out.println(JSONObject.toJSONString(authentication, true));System.out.println("userDetails :");System.out.println(JSONObject.toJSONString(userDetails, true));return "请求成功";}@GetMapping(value = {"/user/select", "/admin/select"})@ResponseBodypublic Object select() {return "Select";}@GetMapping(value = {"/user/create", "/admin/create"})@ResponseBodypublic Object create() {return "Create";}@GetMapping(value = {"/user/update", "/admin/update"})@ResponseBodypublic Object update() {return "Update";}@GetMapping(value = {"/user/delete", "/admin/delete"})@ResponseBodypublic Object delete() {return "Delete";}
}

5、首页,访问链接,便于测试

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head><meta charset="UTF-8"><title>首页</title>
</head>
<body>
<h2><a href="/hello"> hello </a>
</h2><h3>user</h3>
<h4><a href="/user">User角色</a>
</h4>
<p><a href="/user/select">User角色,拥有 select 权限</a></p>
<p><a href="/user/create">User角色,拥有 create 权限</a></p>
<p><a href="/user/update">User角色,拥有 update 权限</a></p>
<p><a href="/user/delete">User角色,拥有 delete 权限</a></p><h3>admin</h3>
<h4><a href="/admin">Admin角色</a>
</h4>
<p><a href="/admin/select">Admin角色,拥有 select 权限</a></p>
<p><a href="/admin/create">Admin角色,拥有 create 权限</a></p>
<p><a href="/admin/update">Admin角色,拥有 update 权限</a></p>
<p><a href="/admin/delete">Admin角色,拥有 delete 权限</a></p>
</body>
</html>

6、测试 roles 权限

拥有用户:
admin --> ADMIN、USER
yzm --> USER

@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {// 从内存创建用户auth.inMemoryAuthentication().withUser("admin")// 密码需要加密,不加就提示错误.password(passwordEncoder().encode("123456"))// 基于内存创建的用户不能同时使用roles和authorities,如果同时使用只有后面的生效,这个坑.roles("ADMIN", "USER")//.authorities("select", "delete").and().withUser("yzm").password(passwordEncoder().encode("123456")).roles("USER")//.authorities("select");}

启动项目 访问 / 或 /home 首页接口,由于是放行的,所以可以访问

点击 hello 跳转到Security默认提供的登录页面

.authorizeRequests().antMatchers("/home", "/").permitAll() //指定url放行.antMatchers("/user/**").hasAnyRole("ADMIN", "USER") // 需要角色(二选一).antMatchers("/admin/**").hasRole("ADMIN") // 需要角色.anyRequest().authenticated() //其他任何请求都需要身份认证.and()

在前面我们没有拦截/hello,它走的是需要认证 即.anyRequest().authenticated()
没有认证的请求,默认转发到 /login

开始登录yzm


登录成功之后,继续之前的 /hello 请求

如果我们创建内存用户不是使用加密的,而是直接明文
把.password(passwordEncoder().encode(“123456”)) 改成 .password(“123456”)
那么我们点击登录,就会提示下面的错误


提示 Encoded password does not look like BCrypt (密码没有加密)

回到首页,此时登录用户:yzm,能访问部分接口

点击 user角色 可以查看当前登录的用户信息

authentication :
{"authenticated":true,"authorities":[{"authority":"user:select"}],"details":{"remoteAddress":"0:0:0:0:0:0:0:1","sessionId":"20A8546453B14E0C3B066A8150B44B9D"},"name":"yzm","principal":{"accountNonExpired":true,"accountNonLocked":true,"authorities":[{"$ref":"$.authorities[0]"}],"credentialsNonExpired":true,"enabled":true,"username":"yzm"}
}
userDetails :
{"accountNonExpired":true,"accountNonLocked":true,"authorities":[{"authority":"user:select"}],"credentialsNonExpired":true,"enabled":true,"username":"yzm"
}

Authentication 用户认证对象 ,内容比较多并且包含了 UserDetails信息
UserDetails 用户详情对象

访问 localhost:8080/logout 退出登录

登录admin,admin有双重身份,可以访问所有的接口

7、测试 authorities 权限

admin --> admin:select、admin:delete
yzm --> user:select

    @Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("admin").password(passwordEncoder().encode("123456"))// 基于内存创建的用户不能同时使用roles和authorities,如果同时使用只有后面的生效,这个坑//.roles("ADMIN", "USER").authorities("admin:select", "admin:delete").and().withUser("yzm").password(passwordEncoder().encode("123456"))//.roles("USER").authorities("user:select");}@Overrideprotected void configure(HttpSecurity http) throws Exception {http....antMatchers("/user/select").hasAuthority("user:select") // 需要权限.antMatchers("/user/delete").hasAuthority("user:delete").antMatchers("/admin/select").hasAuthority("admin:select").antMatchers("/admin/delete").hasAnyAuthority("admin:delete", "admin:remove") // 需要权限(二选一).anyRequest().authenticated() //其他任何请求都需要身份认证.and();}

重启项目

8、问题

.withUser("admin")// 密码需要加密,不加就提示错误.password(passwordEncoder().encode("123456"))// 基于内存创建的用户不能同时使用roles和authorities,如果同时使用只有后面的生效,这个坑//.roles("ADMIN", "USER").authorities("admin:select", "admin:delete")

在上面的代码中 roles() 跟 authorities() 能不能同时设置?
可以同时设置,但只有最后设置的那个有效,后面设置的会替换掉前面设置的
我们可以看下它们的实现

        public UserDetailsManagerConfigurer<B, C>.UserDetailsBuilder roles(String... roles) {this.user.roles(roles);return this;}public UserDetailsManagerConfigurer<B, C>.UserDetailsBuilder authorities(GrantedAuthority... authorities) {this.user.authorities(authorities);return this;}
     public UserBuilder roles(String... roles) {List<GrantedAuthority> authorities = new ArrayList<>(roles.length);for (String role : roles) {Assert.isTrue(!role.startsWith("ROLE_"),() -> role + " cannot start with ROLE_ (it is automatically added)");authorities.add(new SimpleGrantedAuthority("ROLE_" + role));}// roles最后是调用authorities()方法的return authorities(authorities);}public UserBuilder authorities(GrantedAuthority... authorities) {return authorities(Arrays.asList(authorities));}public UserBuilder authorities(Collection<? extends GrantedAuthority> authorities) {this.authorities = new ArrayList<>(authorities);return this;}

可以看到roles和authorities最后都是给authorities赋值,使用户拥有对应的角色权限
所以我们一般设置一个就可以了

相关链接

首页
下一篇:入门篇

Security之基础篇相关推荐

  1. 鸟哥的Linux私房菜(基础篇)- 第二十六章、Linux 核心编译与管理

    第二十六章.Linux核心编译与管理 最近升级日期:2009/09/18 我们说的 Linux 其实指的就是核心 (kernel) 而已.这个核心控制你主机的所有硬件并提供系统所有的功能,所以说,他重 ...

  2. 鸟哥的Linux私房菜(基础篇)- 第十八章、认识系统服务 (daemons)

    第十八章.认识系统服务 (daemons) 最近升级日期:2009/09/14 在 Unix-Like 的系统中,你会常常听到 daemon 这个字眼!那么什么是传说中的 daemon呢?这些 dae ...

  3. SpringSecurity - 基础篇

    文章目录 一.SpringSecurity能做什么 二.SpringSecurity替代方案 三.权限管理中的相关概念 四.SpringSecurity 入门案例 前言:通常我们写http接口是不会用 ...

  4. 重温《数据库系统概论》【第一篇 基础篇】【第1章 绪论】

    时隔两年,重温数据库,再次学习人大教授王珊.萨师煊的<数据库系统概论>,别有一番滋味在心头,或许这就是软件"不归路"上的感悟吧,又一次打开课本,记忆犹新,在已经学习过大 ...

  5. Nginx实战基础篇六 通过源码包编译安装部署LNMP搭建Discuz论坛

    Nginx实战基础篇六 通过源码包编译安装部署LNMP搭建Discuz论坛 版权声明: 本文遵循"署名非商业性使用相同方式共享 2.5 中国大陆"协议 您可以自由复制.发行.展览. ...

  6. 尚硅谷docker基础篇 2018版

    typora-root-url: ./image Docker基础篇之快速上手 第一章 Docker简介 是什么? 问题:为什么会有 docker 的出现 一款产品从开发到上线,从操作系统,到运行环境 ...

  7. 一文搞懂AWS EC2, IGW, RT, NAT, SG 基础篇下

    B站实操视频更新 跟着拉面学习AWS--EC2, IGW, RT, NAT, SG 简介 长文多图预警,看结论可以直接拖到"总结"部分 本文承接上一篇文章介绍以下 AWS 基础概念 ...

  8. 最全MySQL基础篇

    文章目录 导入表的问题 第三章_最基本的SELECT语句 1. SQL语言的规则和规范 1) 基本规则 2) SQL大小写规范(建议遵守) 3) 注释 4) 命名规则 2. 基本的SELECT语句 1 ...

  9. SpringBoot【基础篇】

    SpringBoot2[基础篇] 官方网址:https://spring.io/projects/spring-boot#learn 文章目录 SpringBoot2[基础篇] 第一章:springb ...

最新文章

  1. php判断数组不重复的元素,php从数组中随机选择若干不重复元素
  2. tar xvf实现的是什么功能呢?
  3. php 打开报错,php模式下 运行start.php 报错
  4. 哎哟我去!betterzip居然支持这么多压缩格式!
  5. Spring AOP切面的时候参数的传递
  6. 主线科技完成A轮融资,蔚来资本、普洛斯隐山资本联合领投
  7. 【NLP】 理解NLP中网红特征抽取器Tranformer
  8. 奎屯电信助力智慧城市光网建设
  9. Iterator 遍历器的简单使用
  10. Idea 设置Eclipse快捷键(常用)
  11. [Leetcode][第98 450 700 701题][JAVA][二叉搜索树的合法性、增、删、查][递归][深度遍历]
  12. 面试-重写基础功能函数
  13. 厦门大学计算机学硕复试,【图片】一战厦大计算机上岸,经验帖。慢更【考研吧】_百度贴吧...
  14. [转]JDK动态代理
  15. 华为手机明年全面升级鸿蒙OS:其实两年前就能用
  16. Mac 下载破译版本 secureFX 和 secureCRT
  17. 用python计算方程的根_Python程序计算ax^2+bx+c=0方程根
  18. Go原生插件使用问题全解析
  19. hackthebox - blunder (Bludit渗透cewl使用 sudo提权)
  20. 【Linux性能分析】火焰图(Flame Graphs)的安装和基本用法

热门文章

  1. 使用OpenSSL生成自签名证书和格式转换
  2. 我国现行消费税存在的问题与完善建议
  3. VS好用系列之代码片段
  4. binder 红黑树rb_node转实体对象
  5. html div 子元素 过多 卡顿,CSS浏览器兼容
  6. Java模拟Http请求远程接口
  7. C# 天敏 SDK3000 二次开发时出的问题?? 求解
  8. 利用prolog实现电影助手
  9. web应用存在的10大安全问题
  10. crdownload格式的打开方法。