Spring Security原理
Spring Security的原理主要基于过滤器链的概念。在Web应用程序中,每个请求都会通过一系列的过滤器,Spring Security就是在这个过程中介入并进行安全相关的操作。
Spring Security的核心原理可以概括为以下几点:
1. 认证(Authentication):认证是验证用户身份的过程。用户提供用户名和密码,通过Spring Security的认证过程进行验证。认证可以使用内置的用户名密码验证、LDAP、数据库验证或自定义验证等。
2. 授权(Authorization):授权是检查用户对资源的访问权限。一旦用户身份被认证,Spring Security会根据定义的授权策略来确定用户是否有权访问请求的资源。
3. 过滤器链(Filter Chain):Spring Security的核心机制是通过一系列的过滤器链来处理请求。每个过滤器负责不同的安全任务,比如身份验证、授权、会话管理等。过滤器链可以根据应用程序的需求进行定制和配置。
4. 安全上下文(Security Context):安全上下文是Spring Security用于存储当前用户的安全信息,比如认证信息、授权信息等。安全上下文可以通过`SecurityContextHolder`来访问和管理。
5. 注解支持:Spring Security提供了一组注解,可以在应用程序中方便地进行权限控制。例如,@PreAuthorize
注解可以用于在方法级别进行授权检查。
总结来说,Spring Security通过认证、授权和过滤器链的机制,提供了一套完整的安全解决方案,可以保护应用程序免受未经授权的访问。它的灵活性和易用性使得开发人员可以快速集成和定制安全功能。
tomcat容器结构
java web工作结构
security工作原理
为什么要结合JWT使用?
Spring Security与JWT(JSON Web Token)的结合在实际应用中使用的场景比较多,主要有以下几个原因:
1. 基于令牌的无状态身份验证:JWT是一种基于令牌的身份验证机制,使用签名和加密来保证令牌的安全性。相比使用传统的session和cookie来管理用户状态,JWT具有无状态性(无需在后端存储会话信息)和可扩展性的优势,适用于分布式系统和微服务架构,实现了Session共享.
2. 面向移动端和单页应用:对于移动端和单页应用,传统的session和cookie机制不够灵活,而JWT通过将身份验证信息存储在令牌中,便于在客户端和服务器之间进行传递和验证。JWT可以作为一个轻量级的令牌被存储在移动应用或前端应用的本地存储中,在每次请求时进行身份验证。
3. 跨域和分布式系统:在分布式系统中,不同服务可能由不同的域提供,因此可能会遇到跨域请求的问题。JWT通过将身份验证信息包含在请求头中,不受同源策略的限制,可以在不同域之间进行安全的身份验证和授权传递。
4. 可扩展的自定义声明:JWT除了包含基本的身份验证信息外,还可以包含自定义的声明(Claims),这些声明可以用于传递更多的用户信息或其他业务数据。在使用JWT的过程中,可以根据实际需求自定义声明的内容,方便灵活地扩展应用功能。
5. Spring Security的集成:Spring Security提供了与JWT的集成支持,可以方便地通过配置和过滤器来实现JWT的解析和验证。通过Spring Security的强大功能,可以轻松实现角色和权限的控制,同时与其他Spring生态系统的模块(如Spring Boot)集成。
综上所述,Spring Security与JWT的结合在分布式系统、移动端和单页应用等场景下具备灵活性、可扩展性和安全性,因此被广泛应用于现代Web应用程序的身份验证和授权中。
说白了JWT有不可替代的优势,但Security也有使用的便利性(已内置了很多权限验证功能),所以我们要结合一起使用,结合的时候,我们只使用Security鉴权功能,登陆功能不需要,因为我们已经自己实现了JWT相关的登陆接口,只是登陆成功后我们要把用户的角色Role写进token就可以了.
使用步骤
添加Spring Security依赖
在你的Spring Boot项目的pom.xml文件中,添加Spring Security的依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>
添加SecurityConfig配置
@Configuration
@EnableWebSecurity //开启spring security,可以省略
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable(); //禁用跨域功能http.logout().disable(); //禁用注销功能http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);//禁用session功能http .authorizeRequests().antMatchers("/api/user/register","/api/user/login").anonymous() //antMatchers可以精细化配置.anyRequest().authenticated(); //除了上面的配置以外,所有的请求都需要认证http.addFilter(new TokenFilter(this.authenticationManager())); //把token里面的角色方法SecurityContextHolder里面http.exceptionHandling().authenticationEntryPoint((request,response,authException)->{response.setContentType("application/json; charset=utf-8");response.getWriter().write("{'code':403,'msg':'权限不足'}");});}public static class TokenFilter extends BasicAuthenticationFilter {public TokenFilter(AuthenticationManager authenticationManager) {super(authenticationManager);}@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {String token = request.getHeader("token");if(ObjUtil.isNotEmpty(token)){LocalUser localUser = JSONUtil.toBean(JWTUtil.parseToken(token).getPayload().toString(),LocalUser.class);List<GrantedAuthority> grantedAuthorities = new ArrayList<>();String[] roles = localUser.getRoles();for (String role : roles) {//ROLE_ 一定要加上,否则会报错,它是为了兼容老的规则grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_"+role));}UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(localUser.getId(), // 用户名"",grantedAuthorities); // 角色列表SecurityContextHolder.getContext().setAuthentication(authentication);}chain.doFilter(request, response);}}
}