Spring Security

Spring Security

spring security目的:验证,授权,攻击防护。
spring security原理:创建大量的filter和interceptor来进行请求的验证和拦截,以此来达到安全的效果。
spring security本质:是一个过滤链,有很多过滤器
FilterSecurityInterceptor:访问授权,是一个方法级的权限过滤器,基本位于过滤器的最底部;
ExceptionTranslationFilter:异常过滤器,处理在认证过程中抛出的异常;
UsernamePasswordAuthenticationFilter:基于用户名和密码的身份验证过滤器,对/login的POST请求做拦截,校验表单中用户名、密码;
UserDetailsService:可以通过loadUserByUsername获取UserDetails对象。该接口供spring security进行用户验证。通常使用自定义一个CustomUserDetailsService来实现UserDetailsService接口,通过自定义查询UserDetails。【查询数据库用户名和密码过程】
AuthenticationManager:用来进行验证,如果验证失败会抛出相对应的异常*
PasswordEncoder:密码加密器
BCryptPasswordEncoder:哈希算法加密
NoOpPasswordEncoder:不使用加密
WebSecurityConfigurerAdapter:
AuthenticationManagerBuilder:
JwtAuthenticationFilter:登录认证检查过滤器
JwtLoginFilter:登录认证过滤器
LogoutFilter:登出过滤器
ResourceServerConfigurerAdapter:资源认证服务配置
AuthorizationServerSecurityConfigurer:授权认证服务配置
*
*
TokenLoginFilter
TokenAuthFilter
BasicAuthenticationFilter
*
*
1、pom.xml 文件中添加依赖
spring-boot-starter-web
spring-boot-starter-security
jjwt
fastjson

<?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>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demoSecurity</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demoSecurity</name>
    <description>demoSecurity</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>

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

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

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2、添加一个TestController【使用默认用户和随机生成的密码登录】

package com.example.demos.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class TestController {

    @GetMapping("hello")
    public String hello() {
        return "hello";
    }
}

启动项目,这样在启动的时候会在控制台显示随机生成的密码
spring security 默认的用户名是user,启动的时候会在控制台显示随机生成的密码

访问http://localhost:8080/test/hello
重定向到http://localhost:8080/login,这个页面是spring默认的

填入user 和 上图显示的81b60805-e799-4596-a404-17616dc56ecf,那么就会正常的访问/test/hello接口

*
3、配置文件,使用yml文件定义的用户名、密码登录【配置文件】


spring:
  security:
    user:
      name: root
      password: root

输入root/root登录,可以正常访问/test/hello接口
4、配置类,实现用户名、密码登录【配置类】【默认配置】

package com.example.demosecurity0218.config;

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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity //加不加好像都行
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin").password(passwordEncoder().encode("123456")).roles("admin")
                .and()
                .withUser("user").password(passwordEncoder().encode("123456")).roles("user");
    }

    /**
     * anyRequest          |   匹配所有请求路径
     * access              |   SpringEl表达式结果为true时可以访问
     * anonymous           |   匿名可以访问
     * denyAll             |   用户不能访问
     * fullyAuthenticated  |   用户完全认证可以访问(非remember-me下自动登录)
     * hasAnyAuthority     |   如果有参数,参数表示权限,则其中任何一个权限可以访问
     * hasAnyRole          |   如果有参数,参数表示角色,则其中任何一个角色可以访问
     * hasAuthority        |   如果有参数,参数表示权限,则其权限可以访问
     * hasIpAddress        |   如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
     * hasRole             |   如果有参数,参数表示角色,则其角色可以访问
     * permitAll           |   用户可以任意访问
     * rememberMe          |   允许通过remember-me登录的用户访问
     * authenticated       |   用户登录后可访问
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .formLogin() // 表单登录
                .and()
                .authorizeRequests() // 认证配置
                .anyRequest() // 所有请求
                .authenticated() // 用户登录后可访问
                .and()
                .httpBasic(); // 都需要身份验证
    }
}

访问http://localhost:8080/test/hello
重定向到http://localhost:8080/login,这个页面是spring默认的
填入用户名:admin,密码:123456,那么就会正常的访问/test/hello接口

5、配置类,实现用户名、密码登录【配置类】
新建 config 包,新建 SecurityCofig.java 文件

package com.example.demos.config;

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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.net.PasswordAuthentication;

@Configuration
@EnableWebSecurity
//@EnableWebSecurity(debug = true)
//@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityCofig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .inMemoryAuthentication()
                .withUser("admin").password(passwordEncoder().encode("123456")).roles("ADMIN")
                .and()
                .withUser("user").password(passwordEncoder().encode("123456")).roles("USER")
                .and()
                .withUser("king").password(passwordEncoder().encode("123456")).roles("USER", "ADMIN");;
    }

    /**
     * anyRequest          |   匹配所有请求路径
     * access              |   SpringEl表达式结果为true时可以访问
     * anonymous           |   匿名可以访问
     * denyAll             |   用户不能访问
     * fullyAuthenticated  |   用户完全认证可以访问(非remember-me下自动登录)
     * hasAnyAuthority     |   如果有参数,参数表示权限,则其中任何一个权限可以访问
     * hasAnyRole          |   如果有参数,参数表示角色,则其中任何一个角色可以访问
     * hasAuthority        |   如果有参数,参数表示权限,则其权限可以访问
     * hasIpAddress        |   如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
     * hasRole             |   如果有参数,参数表示角色,则其角色可以访问
     * permitAll           |   用户可以任意访问
     * rememberMe          |   允许通过remember-me登录的用户访问
     * authenticated       |   用户登录后可访问
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        //没有访问权限跳转到自定义页面
        http.exceptionHandling().accessDeniedPage("/unauth.html");

        /**
         * 方式1:默认配置
         * 所有的请求访问都需要被授权。
         * 使用 form 表单进行登陆(默认路径为/login)。
         * 防止 CSRF 攻击、 XSS 攻击。
         * 启用 HTTP Basic 认证
         */
        http.
                authorizeRequests().
                anyRequest().authenticated().
                and().
                formLogin().
                and().
                httpBasic();


        /**
         * 方式2:高级配置
         */
        http
                // CSRF禁用,因为不使用session
                .csrf().disable()
                // 过滤请求
                .authorizeRequests()
                // 对于登录login 验证码captchaImage 允许匿名访问
                .antMatchers("/login", "/captchaImage").anonymous()
                .antMatchers(
                        HttpMethod.GET,
                        "/*.html",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js"
                ).permitAll()
                .antMatchers("/profile/**").permitAll()
                .antMatchers("/common/download**").permitAll()
                .antMatchers("/common/download/resource**").permitAll()
                .antMatchers("/swagger-ui.html").permitAll()
                .antMatchers("/swagger-resources/**").permitAll()
                .antMatchers("/webjars/**").permitAll()
                .antMatchers("/*/api-docs").permitAll()
                .antMatchers("/druid/**").permitAll()
                .antMatchers("/flowable/**").permitAll()
                .antMatchers("/socket/**").permitAll()
                .antMatchers("/user/**").permitAll()
                .antMatchers("/api/common/**").permitAll()
                .antMatchers("/api/contract/**").permitAll()
                .antMatchers("/api/project/**").permitAll()
                .antMatchers("/api/document/**").permitAll()
                .antMatchers("/api/purchase/**").permitAll()
                .antMatchers("/login","/oauth/authorize").permitAll()//设置哪些路径可以直接访问,不需要认证.formLogin() //自定义编写登录页面
                .antMatchers("/login","/oauth/authorize").hasAuthority("")
                .antMatchers("/login","/oauth/authorize").hasAnyAuthority("")
                .antMatchers("/login","/oauth/authorize").hasRole("")
                .antMatchers("/login","/oauth/authorize").hasAnyRole("")
                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest()
                .authenticated()
                .and()
                //显示 HTTP ERROR 403
                .headers().frameOptions().disable();
                //使用 form 表单进行登陆(默认路径为/login)
                //.formLogin().permitAll();
    }
}

访问http://localhost:8080/test/hello
重定向到http://localhost:8080/login,这个页面是spring默认的
填入用户名:admin,密码:123456,那么就会正常的访问/test/hello接口

6、自定义实现类【UserDetailsService】
在 config 包,新建 MySecurityConfiguration.java 文件

package com.example.demos.config;

import org.springframework.beans.factory.annotation.Autowired;
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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class MySecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(password());
    }

    @Bean
    PasswordEncoder password(){
        return new BCryptPasswordEncoder();
    }
}

新建 service 包,新建 MyUserDetailsService.java 文件

package com.example.demos.service;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //可以查询数据库

        List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
        return new User("admin",new BCryptPasswordEncoder().encode("123123"),authorities);
    }
}

输入admin/123123登录,可以正常访问/test/hello接口

7、hasAuthority、hasAnyAuthority、hasRole、hasAnyRole
.antMatchers("/login","/oauth/authorize").hasAuthority("")
.antMatchers("/login","/oauth/authorize").hasAnyAuthority("")
.antMatchers("/login","/oauth/authorize").hasRole("")
.antMatchers("/login","/oauth/authorize").hasAnyRole("")




8、配置文件
跨域配合文件:CorsConfig.java
接口生成文件:SwaggerConfig.java
安全配置文件:WebSecurityConfig.java

8.1、CorsConfig.java 跨域配置 

import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").
                allowedOrigins("https://www.***.com"). //允许跨域的域名,可以用*表示允许任何域名使用
                allowedMethods("GET", "POST", "DELETE", "PUT").
                //allowedMethods("*"). //允许任何方法(post、get等)
                allowCredentials(true). //带上cookie信息
                allowedHeaders("*"). //允许任何请求头
                maxAge(3600).
                exposedHeaders(HttpHeaders.SET_COOKIE).maxAge(3600L); //maxAge(3600)表明在3600秒内,不需要再发送预检验请求,可以缓存该结果
    }
}

8.2、SwaggerConfig.java
*
*
*
8.3、WebSecurityConfig.java
*
*
*
*
*
*
*

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值