关于springsecurity的原理上次小伙伴们都已经粗略了解了下,本篇本站小编将带大家深入了解springsecurity的各种方法原理及实现,快来看看吧。
原理
核心组件:
SecurityContext
public interface SecurityContext extends Serializable { /** * Obtains the currently authenticated principal, or an authentication request token. * * @return the <code>Authentication</code> or <code>null</code> if no authentication * information is available */ Authentication getAuthentication(); /** * Changes the currently authenticated principal, or removes the authentication * information. * * @param authentication the new <code>Authentication</code> token, or * <code>null</code> if no further authentication information should be stored */ void setAuthentication(Authentication authentication); }
安全上下文,用户通过Spring Security 的校验之后,验证信息存储在SecurityContext中,SecurityContext接口定义如下:
public interface SecurityContext extends Serializable { /** * Obtains the currently authenticated principal, or an authentication request token. * * @return the <code>Authentication</code> or <code>null</code> if no authentication * information is available */ Authentication getAuthentication(); /** * Changes the currently authenticated principal, or removes the authentication * information. * * @param authentication the new <code>Authentication</code> token, or * <code>null</code> if no further authentication information should be stored */ void setAuthentication(Authentication authentication); }
SecurityContextHolder
SecurityContextHolder看名知义, 是一个holder, 用来hold住SecurityContext实例的。 其作用就是存储当前认证信息。 在典型的web应用程序中, 用户登录一次, 然后由其会话ID标识。 服务器缓存持续时间会话的主体信息。 在Spring Security中, 在请求之间存储SecurityContext的责任落在SecurityContextPersistenceFilter上, 默认情况下, 该上下文将上下文存储为HTTP请求之间的HttpSession属性。 它会为每个请求恢复上下文SecurityContextHolder, 并且最重要的是, 在请求完成时清除SecurityContextHolder。 SecurityContextHolder是一个类, 他的功能方法都是静态的( static)。 SecurityContextHolder可以设置指定JVM策略( SecurityContext的存储策略), 这个策略有三种: 1. MODE_THREADLOCAL: SecurityContext 存储在线程中。 2. MODE_INHERITABLETHREADLOCAL: SecurityContext 存储在线程中, 但子线程可以获取到父线程中的 SecurityContext。 3. MODE_GLOBAL: SecurityContext 在所有线程中都相同。 SecurityContextHolder默认使用MODE_THREADLOCAL模式, 即存储在当前线程中。 在spring security应用中, 我们通常能看到类似如下的代码: SecurityContextHolder.getContext() .setAuthentication(token);
UserDetails
public interface UserDetails extends Serializable { Collection < ? extends GrantedAuthority > getAuthorities(); String getPassword(); String getUsername(); boolean isAccountNonExpired(); boolean isAccountNonLocked(); boolean isCredentialsNonExpired(); boolean isEnabled(); }
UserDetails名为用户信息。存储的就是用户信息,定义如下:
public interface UserDetails extends Serializable { Collection < ? extends GrantedAuthority > getAuthorities(); String getPassword(); String getUsername(); boolean isAccountNonExpired(); boolean isAccountNonLocked(); boolean isCredentialsNonExpired(); boolean isEnabled(); }
AuthenticationManager
一个接口,只有一个方法,接收参数为Authentication,定义如下:
public interface AuthenticationManager { Authentication authenticate(Authentication authentication) throws AuthenticationException; }
Authentication
名为“认证”的意思,在Spring Security 中用来表示当前用户是谁,可以理解为authentication就是一组用户名密码信息。它也是一个接口,定义如下:
public interface Authentication extends Principal, Serializable { Collection < ? extends GrantedAuthority > getAuthorities(); Object getCredentials(); Object getDetails(); Object getPrincipal(); boolean isAuthenticated(); void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException; }
实现:
一个简单的springboot测试:
@Controller public class AppController { @RequestMapping("/hello") @ResponseBody String home() { return "Hello ,spring security!"; } }
在springboot项目中pom.xml中引入springsecurity:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
配置文件写入
security.basic.enabled = false
spring security会默认提供表单登录功能。我们新建一个类SecurityConfiguration,并加入一些代码,如下所示:
@Configuration @EnableWebSecurity public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest() .authenticated() .and() .formLogin() .and() .httpBasic(); } }
编写简单登录页面
<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'> <h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'> <table> <tr><td>User:</td><td><input type='text' name='username' value=''></td></tr> <tr><td>Password:</td><td><input type='password' name='password'/></td></tr> <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr> <input name="_csrf" type="hidden" value="635780a5-6853-4fcd-ba14-77db85dbd8bd" /> </table> </form></body></html>
再加入配置文件:
security.user.name = admin security.user.password = admin
现在我们给系统增加“/product” 代表商品信息方面的资源(USER可以访问);增加"/admin"代码管理员方面的资源(USER不能访问)。代码如下:
@Controller @RequestMapping("/product") public class ProductTestController { @RequestMapping("/info") @ResponseBody public String productInfo() { return " some product info "; } } -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - @Controller @RequestMapping("/admin") public class AdminTestController { @RequestMapping("/home") @ResponseBody public String productInfo() { return " admin home page "; } }
以上就是本篇文章的所有内容,小伙伴们还有什么不懂得吗?还有关于java架构师的疑问的话,请记得来本网站查找答案。
推荐阅读: