当前位置: 首页 > news >正文

springboot学习之授权Spring Security

SpringSecurity核心功能:认证、授权、攻击防护(防止伪造身份)

涉及的依赖如下:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
 
 

  



新建一个项目,添加如上依赖【添加依赖之后默认开始授权验证】,在控制器controller中测试,指定url,比如
@Controller
public class UserController {

    @RequestMapping(value="/hello")
    @ResponseBody
    public String hello(){return "=======Welcome to HelloWorld==============";}
}

  

如上,原本启动项目后,在地址栏中输入http://localhost:8080/hello应该显示返回的内容

然而此次加了安全验证后,不管url中访问的地址是什么,hello还是hello111,均返回login页面,如下

 

此时系统都没有连DB,用户名和密码是什么?

控制台中有消息,比如Using generated security password: 76dade1c-f190-44f8-915c-7a6b6917fb9a【每次随机生成的密码】

将用户名 user 和 密码 76dade1c-f190-44f8-915c-7a6b6917fb9a 填入上面对话框中,点击按钮Sign in

 

 若之前访问的页面是控制器中配置的页面http://localhost:8080/hello

则此时能成功显示

若之前访问的页面是其他的,控制器中未配置的,则重定向后返回页面不存在。

 

当前自己的项目中,总不能用系统生成的密码进行登录获得权限,那不要被别人笑死。

 

进阶阶段:

我简单创建了一张表,希望该表的人输入匹配的用户名和密码后,方能登录。

CREATE TABLE `admin_user`(
`id` int(4) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(100),
`password` VARCHAR(100),
`role` VARCHAR(100),
`realname` VARCHAR(100),
`mobile` VARCHAR(2000),
`state` BIT default 0,
`info` VARCHAR(200),
PRIMARY KEY (`id`)
)ENGINE=InnoDB AUTO_INCREMENT=300;

  塞了几条数据进去,然后我希望用户在页面上进行登录,那我必须还要创建一个User对象,所谓登录就是传入username和password匹配的场景,只要匹配,就登录成功,跳转到之前的url

public class User {

    private int id;
    private String name;
    private String password; 省略 getter and setter}

  

public interface UserService {

    User login(String name, String password);
}

  

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public User login(String name, String password) {
        String sql ="select * from admin_user where username =? and password = ?";
        User user =jdbcTemplate.queryForObject(sql,new UserRowMapper(),name,password);
        return user;

    }
}

  

public class UserRowMapper implements RowMapper<User> {
    @Override
    public User mapRow(ResultSet resultSet, int i) throws SQLException {
        //此处要使用表中的字段,不能使用属性
        int id =resultSet.getInt("id");
        String username = resultSet.getString("username");
        String password = resultSet.getString("password");
        //String role = resultSet.getString("role");

        User user = new User();
        user.setId(id);
        user.setName(username);
        user.setPassword(password);

        return user;
    }
}

  

登录的方法啪啪啪很快就写好了,我要怎么让系统知道,所有的请求,要先进行登录呢,登录的URL是什么?

 

先看看别人的代码,貌似是实现了UserDetailsService 接口,而点进去发现该接口就一个方法

package org.springframework.security.core.userdetails;

public interface UserDetailsService {
    UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}

  通过一个String类型的变量val1,获取用户的详细信息。。。怎么跟我想的不太一样?

再点进去发现UserDetails 也是一个接口

package org.springframework.security.core.userdetails;

import java.io.Serializable;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;

public interface UserDetails extends Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();

    String getPassword();

    String getUsername();

    boolean isAccountNonExpired();

    boolean isAccountNonLocked();

    boolean isCredentialsNonExpired();

    boolean isEnabled();
}

 一个集合,收集权限,结合做过的项目,有的权限是超级管理员,有的权限是普通管理员,又或者有的删,有新增,有更新等等权限;两个返回String的方法;

还有判断账户是否过期,被锁,验证是否过期,是否开启了。。。

 

 看来光看别人的代码,还是丈二和尚摸不着头脑呢,去看看官方文档吧

 

https://spring.io/projects/spring-security

https://spring.io/guides/topicals/spring-security-architecture

 

英文原文我就不粘贴了,翻译过来,大意就是:

应用程序权限归结于两个独立的问题:

1. 你是谁

2. 你有什么样的权限

一般叫法是权限控制 或者 授权

 

下面开始讲框架中的源码,通过看源码可以了解设计的思路

1. 授权策略中主要的接口是AuthenticationManager,并且只有一个方法

public interface AuthenticationManager {

  Authentication authenticate(Authentication authentication)
    throws AuthenticationException;

} 

 验证管理员在方法authenticate()可以做三件事

a. 输入的信息是有效的当事人,验证通过,返回Authentication 

b. 输入的信息是无效的当事人,验证不通过,返回AuthenticationException 

c. 无法判断的时候,返回一个null

看到这儿,就觉得我想通过查询 用户名 = 输入的用户名 且 密码 =输入密码的想法真是异想天开了。

 

 

Filter Chains,过滤链,默认对所有的范文url进行过滤,意味着打开这个网站的任何链接,都弹出授权页面

而如果像如下的例子,则可以在foo下的下url不进行授权验证,说白了,不登录,这个url下也可以访问。 想想日常使用场景,比如总要有个注册页面吧,不能全面链接都要求登录。不注册如何登录呢?

@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER - 10)
public class ApplicationConfigurerAdapter extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.antMatcher("/foo/**")
     ...;
  }
}

  

 

用户登录了之后,要怎么查看个人信息,传入@AuthenticationPrincipal,当事人对象Principal principal

@RequestMapping("/foo")
public String foo(@AuthenticationPrincipal User user) {
  ... // do stuff with user
}

 

@RequestMapping("/foo")
public String foo(Principal principal) {
  Authentication authentication = (Authentication) principal;
  User = (User) authentication.getPrincipal();
  ... // do stuff with user
}

  

 使用规则介绍完了,花了两天把授权一个可用的项目的代码整理出来,贴上github路径

https://github.com/JasmineQian/buglist

 

其中用的是springboot 2.1.2 Realease 版本,和以前的版本稍微有一点区别,比如必须对密码加密校验,So存进去的密码处,必须加密之后存入数据库

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>


程序中验证的用户名和密码

自己建一张表,叫做qa_user,添加如下数据
2 admin $2a$10$A4EZrzoXqj4mVyXiw/fsp.mJ.Ne5aVAMWrMK0mAb2zY7lJ/H6Jryi admin ROLE_USER,ROLE_ADMIN

 

 

 

转载于:https://www.cnblogs.com/qianjinyan/p/10363504.html

相关文章:

  • RSA
  • bzoj 3622 已经没有什么好害怕的了——二项式反演
  • Kendo DropDownListFor值传不回去的小坑
  • Java消息队列三道面试题详解!
  • 高性能两级缓存J2Cache
  • Webpack 4 学习01(基础配置)
  • 我的zsh配置, 2019最新方案
  • Java基础篇
  • 数据库基础SQL知识面试题二
  • 取代Python多进程!伯克利开源分布式框架Ray
  • mysql常用命令汇总
  • 前端知识点整理(待续)
  • Angular 响应式表单 基础例子
  • 2019年2月22日 807. Max Increase to Keep City Skyline
  • 微信小程序:实现悬浮返回和分享按钮
  • $translatePartialLoader加载失败及解决方式
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • CAP理论的例子讲解
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • create-react-app做的留言板
  • Docker容器管理
  • gcc介绍及安装
  • Linux链接文件
  • mysql中InnoDB引擎中页的概念
  • SQLServer之创建数据库快照
  • Webpack 4 学习01(基础配置)
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 翻译--Thinking in React
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 入职第二天:使用koa搭建node server是种怎样的体验
  • 无服务器化是企业 IT 架构的未来吗?
  • 详解移动APP与web APP的区别
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • 自定义函数
  • 阿里云ACE认证之理解CDN技术
  • ​2020 年大前端技术趋势解读
  • ​Kaggle X光肺炎检测比赛第二名方案解析 | CVPR 2020 Workshop
  • ​Spring Boot 分片上传文件
  • ​sqlite3 --- SQLite 数据库 DB-API 2.0 接口模块​
  • # 飞书APP集成平台-数字化落地
  • (12)Linux 常见的三种进程状态
  • (6)STL算法之转换
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (附源码)ssm教师工作量核算统计系统 毕业设计 162307
  • (四)Android布局类型(线性布局LinearLayout)
  • (转)EOS中账户、钱包和密钥的关系
  • .NET 6 在已知拓扑路径的情况下使用 Dijkstra,A*算法搜索最短路径
  • .net core 6 集成和使用 mongodb
  • .net core webapi 部署iis_一键部署VS插件:让.NET开发者更幸福
  • .Net Core与存储过程(一)
  • .NET MVC之AOP
  • .Net Remoting常用部署结构
  • .Net 知识杂记
  • @取消转义
  • [<死锁专题>]