IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring Boot 学习之路之 Spring Security(一) -> 正文阅读

[Java知识库]Spring Boot 学习之路之 Spring Security(一)

????????Spring Security是一种基于 Spring AOP 和 Servlet 过滤器的企业级安全框架,由 spring 官方推出,提供全面的安全性解决方案,它对软件系统中的认证、授权、加密等功能进行封装,并在Spring Boot 技术推出以后,配置方面做了很大的简化。

????????Spring Security 本质是一个过滤链条,其中有比较重要的三条过滤器:

? ? ? ? 1:FilterSecurityInterceptor:是一个方法级的权限过滤器,基本位于过滤器链的最底部。

? ? ? ? 2:ExceptionTranslationFilter:是个异常过滤器,用来处理在认证授权过程中抛出的异常。

? ? ? ? 3:UsernamePasswordAuthenticationFilter:对/login的post请求做拦截,校验表单中的用户名和密码。

? ? ? ? 过滤器加载流程:

? ? ? ? 使用SpringSecurity配置过滤器(DelegatingFilterProxy),在doFilter方法里使用初始化方法,得到一个叫FilterChainProxy的过滤器,在FilterChainProxy过滤器中得到所有的过滤器并加载到过滤链中,在SecurityFilterChain过滤器中调用getFilters方法完成加载。

? ? ? ? 实现Security需要用到两个比较重要的接口:

? ? ? ? 1、UserDetailsService接口:什么都没有配置的时候,登录账号和密码是由Sercurity定义生成,但当我们需要实际的账号和密码时,就需要通过自定义逻辑控制认证逻辑。

? ? ? ? 2、PasswordEncoder接口:数据加密接口,其中BCryptPasswordEncoder是Security官方推荐的密码解析器。表示验证从存储中获取的编码密码与编码后提交的原始密码是否匹配,如果密码匹配,则返回 true,否则返回 false。

? ? ? ? 准备工作(一)构建项目:

????????

?

?

? ? ? ? 下一步?finish后,创建一个简单的controller以及yal配置,完成访问测试:

server:
  port: 8089

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/wanxi?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false
    username: root
    password: 19980801

? ? ? ? ?启动成功后会,访问配置的路径,会看到这样一个页面,此登录页面是security自带的,用户名是"user",密码在你启动时会给出(在下一张图展示)"e8ea2c58-6989-4895-bf3d-6208f0ac8c98"

?

? ? ? ? ?完成用户名及密码的输入后,便能成功访问到想要的效果:

? ? ? ? ?至此,项目创建完成。

? ? ? ? 1、创建至少2个controller,以便测试:

@RestController
public class SecurityController {

    @RequestMapping("/hello")
    public String hello() {
        return "hello springboot !";
    }

    @RequestMapping("/user")
    public String user() {
        return "成功访问user资源。。。";
    }
}

? ? ? ? 2、创建一个自定义的配置类,配置资源认证规则:

@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 第一步,当访问的是hello资源时不需要进行验证。
        http.authorizeRequests()
                .antMatchers("/hello").permitAll() // 放行指定的资源
                .anyRequest().authenticated()
                .and()
                .formLogin();
    }
}

? ? ? ? 配置完成后,再次访问时即可发现,访问hello资源,无需做额外操作,但是访问的不是hello资源时,则会给到一个登录页面,登录成功才能完成资源访问。

? ? ? ? 如果觉得每次需要复制密码登录麻烦,可以去yml里面配置登录用的用户名和密码:

spring:
  security:
    user:
      name: wx
      password: 123456

? ? ? ? 至此,就完成了Security两大部分之一的Authentication:认证。

? ? ? ? 3、接下来,为controller添加访问权限:

@RestController
public class SecurityController {

    @RequestMapping("/hello")
    public String hello() {
        return "hello springboot !";
    }

    @PreAuthorize("hasAuthority('wx:user')")
    @RequestMapping("/user")
    public String user() {
        return "成功访问user资源。。。";
    }

    @PreAuthorize("hasAuthority('wx:other')")
    @RequestMapping("/other")
    public String other() {
        return "成功访问other资源。。。";
    }
}

? ? ? ? 4、创建一个userEntity,并实现UserDetails接口:

public class UserEntity implements UserDetails {
    private long id;
    private String username;
    private String password;

    public void setAuthorities(Set<? extends GrantedAuthority> authorities) {
        this.authorities = authorities;
    }

    private Set<? extends GrantedAuthority> authorities =  new HashSet<>();

    public UserEntity() {
    }

    public UserEntity(long id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public void setName(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String getUsername() {
        return this.username;
    }

    @Override
    public String getPassword() {
        return this.password;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return this.authorities;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    @Override
    public String toString() {
        return "UserEntity{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

? ? ? ? 5、创建一个permission实体类,并实现GrantedAuthority接口:

public class Permission implements GrantedAuthority {
    private long id;
    private String value;

    @Override
    public String getAuthority() {
        return this.value;
    }

    public Permission() {
    }

    public Permission(long id, String value) {
        this.id = id;
        this.value = value;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "Permission{" +
                "id=" + id +
                ", value='" + value + '\'' +
                '}';
    }
}

????????6、创建myUserDetailsService(该名字最好和UserDetailsService区分开来),因为需要实现UserDetailsService接口:

@Service(value = "myUserDetailsService")
public class MyUserDetailsService implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        UserEntity userEntity = new UserEntity();
        userEntity.setName("wx");
        // 这里密码必须使用加密后的密码,加密规则对应下文配置里的加密方法(我这里用的是BCrypt),password:123456
        userEntity.setPassword("$2a$10$y/j0iaqkWkfgsa6OQtHgieT8Mg5xou0TLkiZ/8F8OzcuHBzSpukxm");

        Permission permission = new Permission();
        //添加权限允许访问规则
        permission.setValue("wx:user");

        Set<Permission> permissionSet = new HashSet<>();
        permissionSet.add(permission);

        userEntity.setAuthorities(permissionSet);

        return userEntity;
    }
}

? ? ? ? 7、修改?MySecurityConfig 配置类:

//@Configuration

//此注解是为controller里的方法添加约束,不至于可以随意访问
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    MyUserDetailsService myUserDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 第一步,当访问的是hello资源时不需要进行验证。
        http.authorizeRequests()
                .antMatchers("/hello").permitAll() // 放行指定的资源
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .userDetailsService(myUserDetailsService);
    }

    /**
     * 为密码进行加密,这个得有
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

? ? ? ? 8、启动入口函数、访问资源:

????????因为对hello资源放行了,因此可以直接访问资源 :

? ? ? ? 然后user资源添加了wx:user的权限,但是为当前用户开放了此权限,因此登录认证后可以访问资源(访问路径是:http:localhost/8089/user, login路径是自动跳转的):

?

? ? ? ? 接下来是加了wx:other权限的other资源,此资源配置了权限,但是并没有对当前用户开放,因此此用户登录后是无法访问该资源的:

? ? ? ? ?至此,登录认证和授权就算成功完成,以上代码亲测有效。

下一篇:Spring Security 加入 mybatis:http://t.csdn.cn/CmOAF???????

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-11-05 00:12:25  更:2022-11-05 00:17:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年3日历 -2025/3/10 18:41:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码