Spring Security用户认证和权限控制(默认实现)

1 背景

实际应用系统中,为了安全起见,一般都必备用户认证(登录)和权限控制的功能,以识别用户是否合法,以及根据权限来控制用户是否能够执行某项操作。

Spring Security是一个安全相关的框架,能够与Spring项目无缝整合,本文主要是介绍Spring Security默认的用户认证和权限控制的使用方法和原理,但不涉及到自定义实现。

Spring Security用户认证和权限控制(自定义实现)这篇文章专门讲解用户认证和权限控制相关的自定义实现。

2 实战示例

2.1 创建工程

创建一个名为authentication-server的spring boot工程,项目结构如下图所示:
在这里插入图片描述
说明:该spring boot工程主要是整合了Spring Security框架和Spring MVC框架。

2.2 配置说明

pom.xml配置文件如下所示:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.authentication.server</groupId>
    <artifactId>authentication-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>authentication-server</name>
    <description>统一用户认证中心</description>

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

    <properties>
        <java.version>1.8</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>
    </dependencies>

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

</project>

application.yml配置文件如下所示:

server:
  port: 8080

2.2 用户认证

要想使用Spring Security框架,配置类需要继承WebSecurityConfigurerAdapter类,并通过注解@EnableWebSecurity来启用Spring Security。

本文的用户认证是使用Spring Security默认的基于用户名和密码的表单认证,需要在配置类中重写protected void configure(AuthenticationManagerBuilder auth)方法,并在重写的方法中指定默认从哪里获取认证用户的信息,即指定一个UserDetailsService接口的实现类。此外,还需要重写protected void configure(HttpSecurity http)方法,并在重写的方法中进行一系列的安全配置。本示例的配置类WebSecurityConfig代码如下所示:

package com.authentication.server.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.EnableWebSecurity;
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;

/**
 * Spring Security配置类
 */
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsServiceImpl;

    /**
     * 用户认证配置
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        /**
         * 指定用户认证时,默认从哪里获取认证用户信息
         */
        auth.userDetailsService(userDetailsServiceImpl);
    }

    /**
     * Http安全配置
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        /**
         * 表单登录:使用默认的表单登录页面和登录端点/login进行登录
         * 退出登录:使用默认的退出登录端点/logout退出登录
         * 记住我:使用默认的“记住我”功能,把记住用户已登录的Token保存在内存里,记住30分钟
         * 权限:除了/toHome和/toUser之外的其它请求都要求用户已登录
         * 注意:Controller中也对URL配置了权限,如果WebSecurityConfig中和Controller中都对某文化URL配置了权限,则取较小的权限
         */
        http
            .formLogin()
                .defaultSuccessUrl("/toHome", false)
                .permitAll()
                .and()
            .logout()
                .permitAll()
                .and()
            .rememberMe()
                .tokenValiditySeconds(1800)
                .and()
            .authorizeRequests()
                .antMatchers("/toHome", "/toUser")
                .permitAll()
                .anyRequest()
                .authenticated();
    }

    /**
     * 密码加密器
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        /**
         * BCryptPasswordEncoder:相同的密码明文每次生成的密文都不同,安全性更高
         */
        return new BCryptPasswordEncoder();
    }

}

Spring Security进行用户认证时,需要根据用户的账号、密码、权限等信息进行认证,因此,需要根据查询到的用户信息封装成一个认证用户对象并交给Spring Security进行认证。查询用户信息并封装成认证用户对象的过程是在UserDetailsService接口的实现类(需要用户自己实现)中完成的。本示例的UserDetailsService接口实现类UserDetailsServiceImpl的代码如下所示:

package com.authentication.server.service.impl;

import com.authentication.server.model.AuthUser;
import com.authentication.server.service.AuthUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 自定义的认证用户获取服务类
 */
@Component("userDetailsServiceImpl")
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private AuthUserService authUserServiceImpl;

    /**
     * 根据用户名获取认证用户信息
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if(StringUtils.isEmpty(username)) {
            throw new UsernameNotFoundException("UserDetailsService没有接收到用户账号");
        } else {
            /**
             * 根据用户名查找用户信息
             */
            AuthUser authUser = authUserServiceImpl.getAuthUserByUsername(username);
            if(authUser == null) {
                throw new UsernameNotFoundException(String.format("用户'%s'不存在", username));
            }
            List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
            for (String role : authUser.getRoles()) {
                //封装用户信息和角色信息到SecurityContextHolder全局缓存中
                grantedAuthorities.add(new SimpleGrantedAuthority(role));
            }
            /**
             * 创建一个用于认证的用户对象并返回,包括:用户名,密码,角色
             */
            return new User(authUser.getUsername(), authUser.getPassword(), grantedAuthorities);
        }
    }
}

查询用户信息的接口AuthUserService 的代码如下所示:

package com.authentication.server.service;

import com.authentication.server.model.AuthUser;

/**
 * 用户服务类
 */
public interface AuthUserService {

    /**
     * 通过用户账号获取认证用户信息
     */
    AuthUser getAuthUserByUsername(String username);

}

查询用户信息的接口实现类AuthUserServiceImpl的代码如下所示:

package com.authentication.server.service.impl;

import com.authentication.server.model.AuthUser;
import com.authentication.server.service.AuthUserService;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * 用户服务实现类
 */
@Service
public class AuthUserServiceImpl implements AuthUserService {

    /**
     * 通过用户账号获取用户信息
     */
    @Override
    public AuthUser getAuthUserByUsername(String username) {
        /**
         * 实际上这里应该是从数据库中查询或者是调用其它服务接口获取,
         * 为了方便,这里直接创建用户信息
         * admin用户拥有 ROLE_ADMIN 和 ROLE_EMPLOYEE 这两个角色
         * employee用户拥有 ROLE_EMPLOYEE 这个角色
         * temp用户没有角色
         */
        if(username.equals("admin")) {
            AuthUser user = new AuthUser();
            user.setId(1L);
            user.setUsername("admin");
            /**
             * 密码为123(通过BCryptPasswordEncoderl加密后的密文)
             */
            user.setPassword("$2a$10$U6g06YmMfRJXcNfLP28TR.xy21u1A5kIeY/OZMKBDVMbn7PGJiaZS");
            List<String> roles = new ArrayList<>();
            roles.add("ROLE_ADMIN");
            roles.add("ROLE_EMPLOYEE");
            user.setRoles(roles);
            return user;
        } else if(username.equals("employee")) {
            AuthUser user = new AuthUser();
            user.setId(2L);
            user.setUsername("employee");
            /**
             * 密码为123(通过BCryptPasswordEncoderl加密后的密文)
             */
            user.setPassword("$2a$10$U6g06YmMfRJXcNfLP28TR.xy21u1A5kIeY/OZMKBDVMbn7PGJiaZS");
            List<String> roles = new ArrayList<>();
            roles.add("ROLE_EMPLOYEE");
            user.setRoles(roles);
            return user;
        } else if (username.equals("temp")) {
            AuthUser user = new AuthUser();
            user.setId(3L);
            user.setUsername("temp");
            /**
             * 密码为123(通过BCryptPasswordEncoderl加密后的密文)
             */
            user.setPassword("$2a$10$U6g06YmMfRJXcNfLP28TR.xy21u1A5kIeY/OZMKBDVMbn7PGJiaZS");
            List<String> roles = new ArrayList<>();
            user.setRoles(roles);
            return user;
        } else {
            return null;
        }
    }

}

用户信息实体类如下所示:

package com.authentication.server.model;

import java.util.List;

/**
 * 用户实体类
 */
public class AuthUser {
    /** 用户ID */
    private Long id;
    /** 用户账号 */
    private String username;
    /** 账号密码 */
    private String password;
    /** 角色集合 */
    private List<String> roles;

    public Long getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

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

    public String getPassword() {
        return password;
    }

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

    public List<String> getRoles() {
        return roles;
    }

    public void setRoles(List<String> roles) {
        this.roles = roles;
    }
}

用户认证成功之后,可以通过@AuthenticationPrincipal注解来获取认证用户信息,本示例中获取认证用户信息的web入口类UserController的代码如下所示:

package com.authentication.server.controller;

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.security.Principal;

/**
 * 用户接口类(返回JSON)
 */
@RestController
public class UserController {

    /**
     * 获取登录后的Principal(需要登录)
     */
    @GetMapping("/getPrincipal")
    public Object getPrincipal(@AuthenticationPrincipal Principal principal){
        return principal;
    }

    /**
     * 获取登录后的UserDetails(需要登录)
     */
    @GetMapping("/getUserDetails")
    public Object getUserDetails(@AuthenticationPrincipal UserDetails userDetails) {
        return userDetails;
    }

}

2.3 权限控制

Spring Security提供了默认的权限控制功能,需要预先分配给用户特定的权限,并指定各项操作执行所要求的权限。用户请求执行某项操作时,Spring Security会先检查用户所拥有的权限是否符合执行该项操作所要求的权限,如果符合,才允许执行该项操作,否则拒绝执行该项操作。

本示例中使用的是Spring Security提供的方法级别的权限控制,即根据权限来控制用户是否能够请求某个方法。首先,需要在工程的主启动类中使用注解@EnableGlobalMethodSecurity(prePostEnabled = true)来启动方法级别的权限控制,并指定是在方法执行之前进行权限验证;然后,需要在方法的入口处通过注解@PreAuthorize()来指定执行对应方法需要什么样的权限。

本示例的主启动类AuthenticationServerApplication的代码如下所示:

package com.authentication.server;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;

/**
 * 主启动类
 */
@ComponentScan("com.authentication.server.*")
@EnableGlobalMethodSecurity(prePostEnabled = true)
@SpringBootApplication
public class AuthenticationServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(AuthenticationServerApplication.class, args);
    }

}

本示例中使用的是基于角色的权限控制,即验证用户所拥有的角色是否符合执行某个方法所需要的角色,如果符合,才允许执行该方法,否则拒绝执行该方法。需要在方法入口处通过注解 @PreAuthorize(“hasRole(‘角色名称’)”)来指定执行对应方法需要什么角色,并且是在执行对应方法之前进行角色验证。

本示例的方法入口控制类PageController的代码如下所示:

package com.authentication.server.controller;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * 页面接口类(页面跳转)
 */
@Controller
public class PageController {

    /**
     * 跳转到admin.html页面(需要登录,且需要ROLE_ADMIN角色)
     */
    @GetMapping("/toAdmin")
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    public String toAdmin() {
        return "admin.html";
    }

    /**
     * 跳转到employee.html页面(需要登录,且需要ROLE_EMPLOYEE角色)
     */
    @GetMapping("/toEmployee")
    @PreAuthorize("hasRole('ROLE_EMPLOYEE')")
    public String toEmployee() {
        return "employee.html";
    }

    /**
     * 跳转到employee.html页面(需要登录,但不需要角色)
     * 注意:虽然WebSecurityConfig中配置了/toUser不需要登录,但是这里配置的权限更小,因此,/toUser以这里的配置为准
     */
    @GetMapping("/toUser")
    @PreAuthorize("isAuthenticated()")
    public String toUser() {
        return "user.html";
    }

    /**
     * 跳转到home.html页面(需要登录,但不需要角色)
     * 注意:虽然这里配置了/toAbout不需要登录,但WebSecurityConfig中配置的权限更小,因此,/toAbout以WebSecurityConfig中配置的为准
     */
    @RequestMapping("/toAbout")
    @PreAuthorize("permitAll")
    public String toAbout() {
        return "about.html";
    }


    /**
     * 跳转到home.html页面(不需要登录)
     */
    @RequestMapping("/toHome")
    public String toHome() {
        return "home.html";
    }

}

静态页面admin.html的代码如下所示:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>admin页面</title>
</head>
<body>
    <h1>这是Admin页面(需要登录,且需要ROLE_ADMIN角色)</h1>
</body>
</html>

静态页面employee.html、user.html、home.html、about.html的代码与admin.html的相似,就不一一展示。

3 功能测试

3.1 用户认证功能测试

运行AuthenticationServerApplication主启动类以启动项目,然后通过浏览器访问以下地址请求toUser()方法(即访问user.html页面),由于toUser()方法需要用户经过认证之后才能访问,因此,会自动跳转到用户认证页面(如下图所示)进行认证:

http://localhost:8080/toUser

在这里插入图片描述
输入用户名admin和密码123并点击Sign in按钮,认证成功后会自动请求/toHome路径并跳转到自定义的认证成功跳转页面home.hmtl(如下图所示):
在这里插入图片描述
通过浏览器访问以下地址可以查看到认证用户信息如下图所示:

http://localhost:8080/getPrincipal
http://localhost:8080/getUserDetails

在这里插入图片描述
在这里插入图片描述

3.2 “记住我” 功能测试

用户进行认证时,如果勾选了用户认证页面中的Remember me on this computer选项,则当用户关闭浏览器之后,系统会记住该用户一段时间(由设置的有效期决定,本示例中是1800秒),如果在这段时间之内,当用户重新访问该系统时,用户不需要重新进行认证就已经是已认证的状态。

使用用户名admin和密码123进行用户认证时勾选上用户认证页面中的Remember me on this computer选项,然后重复执行关闭浏览器后再访问以下地址,并观察关闭了浏览器之后,再重新访问时是跳转到认证页面(未认证状态)还是直接跳转到了user.html页面(已认证状态):

http://localhost:8080/toUser

3.3 退出功能测试

用户认证成功之后,用户就处于已认证的状态,就可以在权限之内访问系统,此时可以通过访问以下地址请求退出已认证状态:

http://localhost:8080/logout

首先会跳转到退出确认页面(如下图所示),用户点击了Log Out按钮之后才会真正的执行退出操作,即回到未认证状态。
在这里插入图片描述

3.4 权限控制功能测试

用户在未认证的情况下通过浏览器访问以下地址请求toAdmin()方法(即访问admin.html页面),由于该方法要求用户已认证且具有ROLE_ADMIN权限才能访问,因此会自动跳转到用户认证页面。

http://localhost:8080/toAdmin

此时如果用用户名employee和密码123进行认证,认证成功之后由于该用户没有ROLE_ADMIN权限,因此会自动跳转到没有权限的页面(如下图所示):
在这里插入图片描述
如果用用户名admin和密码123进行认证,认证成功之后由于该用户拥有ROLE_ADMIN权限,因此会自动跳转到admin.html页面(如下图所示):
在这里插入图片描述
可见,确实起到了权限控制的作用。

4 原理分析

4.1 用户认证的过滤器链

Spring Security的用户认证流程是由一系列的过滤器链来实现的,默认的关于用户认证的过滤器链大致如下图所示:
在这里插入图片描述

  • SecurityContextPersistenceFilter: 在请求开始时,从配置好的 SecurityContextRepository 中获取 SecurityContext,并设置给 SecurityContextHolder。在请求完成后,把 SecurityContextHolder 所持有的SecurityContext 保存到配置好的 SecurityContextRepository,同时清除 securityContextHolder 所持有的 SecurityContext。

  • UsernamePasswordAuthenticationFilter: 用于处理来自表单提交的认证。该表单必须提供用户名和密码,其内部还有登录成功或失败后的处理器 AuthenticationSuccessHandler 和 AuthenticationFailureHandler。

  • ExceptionTranslationFilter: 能够捕获过滤器链中产生的所有异常,但只处理两类异常:AuthenticationException 和 AccessDeniedException,而其它的异常则继续抛出。
    如果捕获到的是 AuthenticationException,那么将会使用其对应的 AuthenticationEntryPoint 的commence()方法进行处理。在处理之前,ExceptionTranslationFilter会先使用 RequestCache 将当前的HttpServerletRequest的信息保存起来,以至于用户登录成功后可以跳转到之前的界面。
    如果捕获到的是 AccessDeniedException,那么将会根据当前访问的用户是否已经登录认证而做不同的处理,如果未登录,则使用关联的 AuthenticationEntryPoint 的 commence()方法进行处理,否则使用关联的 AccessDeniedHandler 的handle()方法进行处理。

  • FilterSecurityInterceptor: 用于保护HTTP资源的,它需要一个 AuthenticationManager 和一个 AccessDecisionManager 的引用。它会从 SecurityContextHolder 中获取 Authentication,然后通过 SecurityMetadataSource 可以得知当前请求是否在请求受保护的资源。对于请求那些受保护的资源,如果 Authentication.isAuthenticated() 返回false(即用户未认证),或者FilterSecurityInterceptor 的 alwaysReauthenticate 属性的值为 true,那么将会使用其引用的 AuthenticationManager 对Authentication进行认证,认证之后再使用认证后的 Authentication 替换 SecurityContextHolder 中原有的那个。然后使用 AccessDecisionManager 对用户当前请求进行权限检查。

4.2 用户认证的流程

Spring Security支持多种用户认证的方式,最常用的是基于用户名和密码的用户认证方式,其认证流程如下图所示:
在这里插入图片描述

4.3 “记住我” 功能的流程

用户可以使用账号和密码进行认证,但是如果用户使用账号和密码进行认证时选择了“记住我”功能,则在有效期内,当用户关闭浏览器后再重新访问服务时,不需要用户再次输入账号和密码重新进行认证,而是通过“记住我”功能自动认证。

“记住我”功能的认证流程如下图所示:
在这里插入图片描述
上述的用户认证处理逻辑都是基于Spring Security提供的默认实现,我们只需要自己实现一个UserDetailsService接口用于获取用户认证信息即可,十分简便。当然,Spring Security也能够支持我们使用自定义的用户认证处理逻辑,我们可以自己实现AuthenticationFilter和AuthenTicationProvider,以达到按照需求进行用户认证的目的。博主的另外一篇文章会专门分享自定义用户认证的实现。

4.4 权限控制的原理

Spring Security允许我们通过Spring EL权限验证表达式来指定访问URL或方法所需要的权限,用户在访问某个URL或方法时,如果对应的权限验证表达式返回结果为true,则表示用户拥有访问该URL或方法的权限,如果返回结果为false,则表示没有权限。Spring Security为我们提供了以下的权限验证表达式:

表达式描述
hasRole([role])当前用户是否拥有指定角色。
hasAnyRole([role1,role2])多个角色是一个以逗号进行分隔的字符串。如果当前用户拥有指定角色中的任意一个则返回true。
hasAuthority([auth])等同于hasRole
hasAnyAuthority([auth1,auth2])等同于hasAnyRole
Principle代表当前用户的principle对象
authentication直接从SecurityContext获取的当前Authentication对象
permitAll总是返回true,表示允许所有的
denyAll总是返回false,表示拒绝所有的
isAnonymous()当前用户是否是一个匿名用户
isRememberMe()表示当前用户是否是通过Remember-Me自动登录的
isAuthenticated()表示当前用户是否已经登录认证成功了。
isFullyAuthenticated()如果当前用户既不是一个匿名用户,同时又不是通过Remember-Me自动登录的,则返回true。

权限验证表达式只能验证用户是否具有访问某个URL或方法的权限,但是权限验证的这个步骤可以在不同的阶段进行。Spring Security中定义了以下四个支持使用权限验证表达式的注解,其中前两者可以用来在方法调用前或者调用后进行权限验证,后两者可以用来对集合类型的参数或者返回值进行过滤:

  • @PreAuthorize
  • @PostAuthorize
  • @PreFilter
  • @PostFilter

权限验证表达式需要和注解结合使用,示例如下所示:

@PreAuthorize("hasRole('ROLE_ADMIN')")
public void addUser(User user) {
   ...
}

@PreAuthorize("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
public User find(int id) {
   return null;
}

@PreAuthorize("#id<10")
public User find(int id) {
   return null;
}

@PreAuthorize("principal.username.equals(#username)")
public User find(String username) {
   return null;
}

@PreAuthorize("#user.name.equals('abc')")
public void add(User user) {
   ...
}

@PostAuthorize("returnObject.id%2==0")
public User find(int id) {
   ...
   return user;
}

@PostFilter("filterObject.id%2==0")
public List<User> findAll() {
   List<User> userList = new ArrayList<User>();
   ...
   return userList;
}

@PreFilter(filterTarget="ids", value="filterObject%2==0")
public void delete(List<Integer> ids, List<String> usernames) {
   ...
}

5 总结

本文从使用方法和原理分析这两个方法简要的介绍了Spring Security的用户认证和权限控制这两大功能,但都是基于Spring Security的默认实现,我们也可以自定义用户认证和权限控制的实现逻辑,Spring Security用户认证和权限控制(自定义实现)详细介绍了用户认证相关和权限控制相关的自定义实现。关于授权服务器、资源服务器的内容可以查阅以下几篇文章:

OAuth2授权服务器和四种授权方式 这篇文章介绍了授权服务器和四种授权方式的配置与使用方法。
OAuth2资源服务器 这篇文章介绍了基于方法级别的权限控制的资源服务器的配置与使用方法。

如果觉得本文对您有帮助,请关注博主的微信公众号,会经常分享一些Java和大数据方面的技术案例!
在这里插入图片描述

  • 55
    点赞
  • 364
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
Spring Security是一个功能强大的身份验证和访问控制框架,用于保护Java应用程序的安全性。它提供了一套全面的安全性解决方案,包括身份验证、授权、密码管理和会话管理等功能。 Spring Security权限控制是通过以下几个核心概念来实现的: 1. 认证(Authentication):认证是验证用户身份的过程。Spring Security支持多种认证方式,包括基于表单、基于HTTP基本认证、基于LDAP等。在认证成功后,Spring Security会将用户的身份信息存储在一个称为SecurityContext的地方,以便后续的授权操作使用。 2. 授权(Authorization):授权是确定用户是否有权限执行某个操作的过程。Spring Security提供了一套灵活的授权机制,可以通过注解、表达式、配置文件等方式进行权限控制。常见的授权方式包括基于角色(Role-based)和基于资源(Resource-based)的授权。 3. 权限(Permission):权限是指用户被授予的特定操作或资源访问的能力。Spring Security支持细粒度的权限控制,可以通过配置角色和权限之间的关系来实现。 4. 过滤器链(Filter Chain):Spring Security通过一系列的过滤器链来处理请求。每个过滤器负责不同的安全功能,例如身份验证、授权、会话管理等。过滤器链的配置可以通过Java配置或XML配置来完成。 5. 安全注解(Security Annotation):Spring Security提供了一系列的注解,用于在方法或类级别上进行权限控制。例如,@PreAuthorize注解可以在方法执行前进行权限检查,如果不满足条件则拒绝访问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值