SpringBoot整合spring-security

内容分享4天前发布
0 0 0

[官方文档]
https://spring.io/projects/spring-security

[官方API地址]
https://docs.spring.io/spring-security/site/docs/5.4.6/api/

概述:

Spring Security是一个提供身份验证、授权和防范常见攻击的框架。由于对命令式应用程序和响应式应用程序都提供了一流的支持,它是保护基于spring的应用程序的实际上的标准。

[核心功能] 主要功能就是身份的认证及授权

SpringBoot+spring-security+jwt实现认证授权实现认证及授权

POM依赖

<dependencies>
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
  </dependency>
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-thymeleaf</artifactId>
  </dependency>
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
  </dependency>
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
  </dependency>
  <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
  </dependency>
  <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>2.1.3</version>
  </dependency>
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-devtools</artifactId>
      <scope>runtime</scope>
      <optional>true</optional>
  </dependency>
  <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <optional>true</optional>
  </dependency>
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
  </dependency>
  <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
  </dependency>
  <!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
  <dependency>
      <groupId>com.auth0</groupId>
      <artifactId>java-jwt</artifactId>
      <version>3.15.0</version>
  </dependency>
  <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.62</version>
  </dependency>
</dependencies>

配置spring-security

package com.yingdongshuju.springsecutity.config;

import com.yingdongshuju.springsecutity.filter.LoginFilter;
import com.yingdongshuju.springsecutity.filter.TokenFilter;
import com.yingdongshuju.springsecutity.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

/**
 * @Author: dawang
 * @Date: 2021/4/13 17:51
 */
@Configuration
@EnableWebSecurity
//开启spring-securty注解功能
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled=true,jsr250Enabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserService userService;



        /**
        *  此方法采用的是链式编程,使用and()方法进行参数的拼接
        **/
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //允许使用RequestMatcher实现(即通过URL模式)基于HttpServletRequest限制访问

        http
                .csrf().disable()               //关闭csrf功能
                        //配置接口路径的权限
//                .authorizeRequests()
//                .antMatchers("/vip/**").hasAnyRole("ADMIN")
//                .antMatchers("/").permitAll()
//                .antMatchers("/success").permitAll()
//                .and()
                        //配置表单登陆
//                .formLogin()
//                .loginProcessingUrl("/doLogin")
//                .loginPage("/login")
//                .permitAll()
//                .and()
                        //这里使用的是过滤器实现登陆认证授权
                .addFilter(new LoginFilter(this.authenticationManager()))
                .addFilter(new TokenFilter(this.authenticationManager()))
                .sessionManagement().disable()
        ;
    }

        //密码加密类
    @Bean
    public PasswordEncoder getPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //来自内存
  /*      auth.inMemoryAuthentication()
                .passwordEncoder(new BCryptPasswordEncoder())
                .withUser("user").password(new BCryptPasswordEncoder().encode("123456")).roles("USER")
                .and()
                .withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("ADMIN", "USER");*/
        //来自数据库
        auth.userDetailsService(userService).passwordEncoder(getPasswordEncoder());
    }

}

[什么是csrf]
https://baike.baidu.com/item/%E8%B7%A8%E7%AB%99%E8%AF%B7%E6%B1%82%E4%BC%AA%E9%80%A0/13777878?fromtitle=CSRF&fromid=2735433&fr=aladdin

授权


/**
 * token过滤器 验证token有效性
 *
 * @author smalljop
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    private final TokenService tokenService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        //log.info("REQUEST_PATH: {}",request.getServletPath());
        //System.err.println("REQUEST_PATH:"+request.getServletPath());
        LoginUserEntity loginUser = tokenService.getLoginUser(request);
        if (ObjectUtil.isNotNull(loginUser) && ObjectUtil.isNull(SecurityUtils.getAuthentication())) {
            tokenService.verifyToken(loginUser);
            //创建授权对象
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            //存入授权内容
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        }
        chain.doFilter(request, response);
    }
}

spring-secutity注解

@EnableGlobalMethodSecurity

在方法上增加Spring Security注解,主要是为了判断当前用户是否有资格执行该方法,如是否拥有某权限、是否为当前登录用户。 spring security默认禁用注解,要想开启注解,需要在继承
WebSecurityConfigurerAdapter的类上加@
EnableGlobalMethodSecurity注解,并在该类中将AuthenticationManager定义为bean。 提供了三种注解。

JSR-250注解

@DenyAll:拒绝所有访问。
@RolesAllowed({“USER”,”ADMIN”}):该方法只要具有USER、ADMIN任意一种权限即可访问。这里省略前缀ROLE_,实际权限可能是ROLE_ADMIN。
@PermitAll:允许所有访问。

prePostEnable注解

开启此注解方法:

@EnableGlobalMethodSecurity(prePostEnabled = true)

@PreAuthorize:在方法执行前判断,可以调用方法参数,主要利用Java8的参数名反射特性,如果没用Java8也可以使用spring security的@P标注参数,或者Spring Data的@Param标注参数。

//通过表达式判断用户是否为当前登录用户或拥有ROLE_ADMIN权限
@PreAuthorize("#userId == authentication.principal.userId or hasAuthority(‘ADMIN’)")
public void changePassword(@P("userId") long userId ){}

SpringBoot整合spring-security

写权限校验

        @GetMapping("/write")
    @RolesAllowed("ROLE_ADMIN")
    @PreAuthorize("hasAuthority('write')")
    @ResponseBody
    public String test01(){
        return "你可以写了";
    }

@PostAuthorize:在方法执行后判断,可以调用参数。如果EL为false,虽然方法已经执行完了也可能会回滚,EL变量returnObject表明返回的对象。

@PostAuthorize
User getUser("returnObject.userId == authentication.principal.userId 
    or hasPermission(returnObject, 'ADMIN')");

@PreFilter:在方法执行前判断,可以调用方法参数,对参数值进行过滤、处理或修改。EL变量filterObject表明参数,如有多个参数则用filterTarget注解参数,那么参数必须是集合或数组才行(很少用到,与分页技术不兼容)。 securedEnable注解 @Secured:是否有权限访问

@Secured("IS_AUTHENTICATED_ANONYMOUSLY") public Account readAccount(Long id);
@Secured("ROLE_TELLER")

配置swagger过滤

import com.yingdongshuju.filter.HeardFilter;
import com.yingdongshuju.filter.LoginFilter;
import com.yingdongshuju.filter.TokenFilter;
import com.yingdongshuju.service.UserService;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;
    @Autowired
    private AccessDeniedHandlerConfig accessDeniedHandlerConfig;
    @Autowired
    private AuthenticationEntryPointConfig authenticationEntryPointConfig;


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //允许使用RequestMatcher实现(即通过URL模式)基于HttpServletRequest限制访问

        http
                .cors()//开启跨域支持
                .and()
                .authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll()
                .and()
                .csrf().disable()//关闭csrf
                .logout().disable()
                .addFilter(new LoginFilter(this.authenticationManager()))//加入登陆过滤器
                .addFilter(new TokenFilter(this.authenticationManager()))//加入token过滤器
                .sessionManagement().disable()//禁用session
        ;
    }


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


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //来自内存
  /*      auth.inMemoryAuthentication()
                .passwordEncoder(new BCryptPasswordEncoder())
                .withUser("user").password(new BCryptPasswordEncoder().encode("123456")).roles("USER")
                .and()
                .withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("ADMIN", "USER");*/
        //来自数据库
        auth.userDetailsService(userService).passwordEncoder(getPasswordEncoder());
    }


    /**
     * 配置静态资源放行
     *
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
                .antMatchers("/v2/api-docs", "/swagger-resources/configuration/ui",
                        "/swagger-resources", "/swagger-resources/configuration/security",
                        "/swagger-ui.html", "/css/**", "/js/**", "/images/**", "/webjars/**", "**/favicon.ico", "/index"
                );
    }

}

协助:

协助文档地址:
https://docs.spring.io/spring-security/site/docs/current/reference/html5/

官方demo地址:
https://docs.spring.io/spring-security/site/docs/current/reference/html5/#samples

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
none
暂无评论...