Spring Security5+ 用户认证、受权及注销

2022年05月13日 阅读数:2
这篇文章主要向大家介绍Spring Security5+ 用户认证、受权及注销,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

目录html

前言java

1、Spring Security 的简单介绍web

2、用户认证与受权算法

一、导入相关依赖spring

二、受权(Authorization)数据库

三、认证 (Authentication)编程

3、用户注销安全


前言

Spring Security是一个专一于为Java应用程序提供身份验证和受权的框架。与全部Spring项目同样,Spring Security的真正强大之处在于它能够很容易地扩展以知足定制需求。虽然拦截器、过滤器也能够在必定程度上起到安全认证的做用,可是对码农来讲,大量原生的代码及代码冗余,十分的不友好。本文以Spring Security5.6.2版原本对用户认证、受权、注销作个说明。网络

1、Spring Security的简单介绍

一、到博主写博客的时间为止,Spring Security已经更新到了5.6.2了,做为Spring全家桶之一,其可谓是出身名门,固然新版本增长了一些功能,但也可能会出现版本不兼容的问题。app

二、功能

1) 对身份验证和受权的全面和可扩展支持

2) 防止攻击,如会话固定,点击劫持,跨站请求伪造等

3) 集成了Servlet API

4) 与Spring Web MVC的可选集成

5) 还定制了一些功能,好比增长了一些加密算法

2、用户认证与受权

一、导入相关依赖

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

注:导入spring-security依赖后,系统会自动过滤,没有进行登陆的话,会自动跳转到Spring Security定制的login界面上 。经过查看源码HttpSecurity.java ,不难发现系统默认自动生成一个登陆页面在URL里显示“/login”,认证失败会重定向到“/login?error”,而且登陆页面的详细信息能够在formloginconfiguration .loginpage (String)中找到。

 

那它定制的登陆界面,咱咋知道它的登陆名和密码呢?你在源码里能够发现大量的hasRole("USER"),登陆名就是它了,甚至还能够小写。那密码呢?运行程序后控制台会自动生成一个秘钥,固然人家会提示你:今生成的密码仅供开发使用。在生产环境中运行应用程序以前,必须更新安全配置。

二、受权(Authorization)

学过网络工程的人,可能会对AAA认证机制有所了解,Cisco开发的一个提供网络安全的系统,包括身份验证(Authentication)、受权 (Authorization)和统计 (Accounting)。那Spring Security的受权怎么配置呢?

1)写一个安全配置类:SecurityConfig,让这个类继承WebSecurityConfigurerAdapter,而后重写configure(HttpSecurity http)方法

 2)受权与拦截验证

通常而言,首页全部人都能访问,功能页只有对应有权限的人才能够访问。那如何定制受权的规则,拦截非受权的请求呢?阅读源码可知,能够经过HttpSecurity的参数名http调用受权请求,而且受权调用方法的形式相似链式编程。

antMatcher用在多个HttpSecurity的场景下,用来为每一个HttpSecurity过滤。没有权限会调用formLogin()方法,回到登陆界面 。好比:我在项目里容许访问项目主路径"/"的请求,其它请求都要通过拦截验证,让不一样的vip跳到它们的专属页面。

 SecurityConfig受权配置以下:

//受权
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //首页全部人能访问,功能页只有对应有权限的人才能够访问
        //请求受权的规则
        http.authorizeHttpRequests().antMatchers("/").permitAll()
                //容许访问项目主路径"/"的请求,其它请求都要通过拦截验证
                .antMatchers("/level1/**").hasRole("vip1")
                .antMatchers("/level2/**").hasRole("vip2")
                .antMatchers("/level3/**").hasRole("vip3");
        //没有权限默认到登陆页面,须要开启登陆的页面
        http.formLogin();

    }

3)结果

配置完成后,系统不会自动跳转到Spring Security定制的login界面上,而是到本身写的主页面index.html上。固然点击不一样vip的专属资源,须要进行登陆认证。

三、认证 (Authentication)

1)认证重写了configure(AuthenticationManagerBuilder auth)方法,数据正常应该从数据库里面读(auth.jdbcAuthentication()),为了方便,本文是从内存里直接读的(auth.inMemoryAuthentication())从内存读取固然也更快一点了。

2)进行认证配置

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    //认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //这些数据正常应该从数据库里面读(auth.jdbcAuthentication()),下面是从内存里读的(auth.inMemoryAuthentication())
        auth.inMemoryAuthentication()
                .withUser("guest")
                .password("{noop}123456")
                .roles("vip1")
                .and().withUser("user")//and()拼接
                .password("{noop}55555")
                .roles("vip1","vip2")
                .and().withUser("admin")
                .password("{noop}root").roles("vip1","vip2","vip3");
    }

在这里,咱们建立了三类用户:

第一类:游客(guest) ,拥有一个查看权限(这里定义为vip1)

第二类:登陆用户(user),拥有查看和操做的权限(这里定义为vip1和vip2)

第三类:管理员(admin),拥有查看、操做和管理的权限(这里定义为vip一、vip2和vip3)

使用.and()进行多用户拼接

3)Spring Security5.0+加密方法说明

当进行以下配置时,会出现500错误,而且出现:There is no PasswordEncoder mapped for the id "null",这是因为新版本中必定要指定密码编码(PasswordEncoder)的方式。

 在Spring Security5.0+中 新增了不少的加密方法。spring security 5支持的加密 方式有bcrypt、ldap、MD四、MD五、noop、pbkdf二、scrypt、SHA-一、SHA-25六、 sha256。

为方便校验测试,{noop}是制定密码加密策略为不加密 。noop的意思是明文保存的密码 (noop: No Operation)。此PasswordEncoder仅用于遗留和测试目的,不被认为是安全的。一个什么都不作的密码编码器,对于使用纯文本密码的测试很是有用。

spring security官方推荐使用更加安全的bcrypt加密方式。该加密方式使用了BCrypt强哈希函数的PasswordEncoder的实现,而且强度参数越大,须要以指数方式对密码进行哈希处理的工做量就越大。

 改善以后的代码以下:

 @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //这些数据正常应该从数据库里面读(auth.jdbcAuthentication()),下面是从内存里读的(auth.inMemoryAuthentication())
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("guest")
                .password(new BCryptPasswordEncoder().encode("123456"))
                .roles("vip1")
                .and().withUser("user")//and()拼接
                .password(new BCryptPasswordEncoder().encode("55555"))
                .roles("vip1","vip2")
                .and().withUser("admin")
                .password(new BCryptPasswordEncoder().encode("root")).roles("vip1","vip2","vip3");

    }

4)结果测试

编写一个Controller类

package com.study.controller;


import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Controller
public class RouterController {
    @RequestMapping({"/", "/index"})
    public String index() {
        return "index";
    }

    @RequestMapping("/toLogin")
    public String toLogin() {
        return "views/login";
    }

    @RequestMapping("/level1/{id}")
    public String level1(@PathVariable("id") int id) {
        return "views/level1/" + id;
    }

    @RequestMapping("/level2/{id}")
    public String level2(@PathVariable("id") int id) {
        return "views/level2/" + id;
    }

    @RequestMapping("/level3/{id}")
    public String level3(@PathVariable("id") int id) {
        return "views/level3/" + id;
    }
}

 结果以下:管理员用户能够访问到vip3下的资源

3、用户注销

一、首先,应该开启注销功能,注销完成以后让它跳转至首页

http.logout().logoutSuccessUrl("/");

二、经过源码注释,可知:HttpSecurity提供注销的支持,在使用WebSecurityConfigurerAdapter时会自动应用。默认状况下,会访问URL“/logout”地址,并使HTTP会话无效、清除配置的任何rememberMe()身份验证、清除SecurityContextHolder,而后重定向到“/login?success”来注销用户。 

三、结果 

注销以后,成功退到首页