安全包括 验证身份和授权,spring对这2部分都进行了支持。
一、基本概念和javase抽象
subject = principal(身份) + credential(凭证)
pricipal的例子:身份证号、用户名、电话号码
credential的例子:密码、证书
Permission:权限
Policy:权限控制策略
AccessController:使用权限
ProtectionDomain:维护了一组身份和权限
加解密:
Cipher 加密服务
MessageDigest 摘要
SecretKey 对称秘钥
PublicKey和PrivateKey 非对称秘钥
KeySpec具体的秘钥的说明
Message Authentication Code (MAC):添加了秘钥的摘要算法
Certificate证书:由发证机构加密过的公钥
签名:(用私钥加密)
Signature signature = Signature.getInstance("SHA1withDSA");
signature.initSign(privateKey);
byte[] data = "Hello World".getBytes();
signature.update(data);
byte[] signatureData = signature.sign(); //得到签名
signature.initVerify(publicKey);
signature.update(data);
boolean result = signature.verify(signatureData); //进行验证
二、spring secure概览
1、基本概念:
UserDetails:安全相关的用户信息
GrantedAuthority[] getAuthorities():用户权限信息
UserDetailsService:loadUserByUsername
Authentication 代表一个和应用程序交互的待认证用户,内部使用UserDetails。
后面的访问控制基于这个类。pricipal + GrantedAuthority
SecurityContext 存储Authentication
SecurityContextHolder 框架层的入口
HttpSession->HttpSessionContextIntegrationFilter
->SecurityContextHolder->SecurityContext ->AuthenticationManager(验证)+AccessDecisionManager(访问控制)
DaoAuthenticationProvider-》UserDetailService
AuthenticationManager: AuthenticationProvider 授权信息注入context
AccessDecisionManager= AccessDecisionVoter(民主投票)
ExceptionTranslationFilter:权限不合适时的异常处理
AuthenticationEntryPoint:登陆入口
2、用户认证过程:
1.你点击一个链接访问一个网页;
2.浏览器发送一个请求到服务器,服务器判断出你正在访问一个受保护的资源;
3.如果此时你并未通过身份认证,服务器发回一个响应提示你进行认证——这个响应可能是一个HTTP响应代码,抑或重定向到一个指定页面;
4.根据系统使用认证机制的不同,浏览器或者重定向到一个登录页面中,或者由浏览器通过一些其它的方式获取你的身份信息(如通过BASIC认证对话框、一 个Cookie或一个X509证书);
5.浏览器再次将用户身份信息发送到服务器上(可能是一个用户登录表单的HTTP POST信息、也可能是包含认证信息的HTTP报文头);
6.服务器判断用户认证信息是否有效,如果无效,一般情况下,浏览器会要求你继续尝试,这意味着返回第3步。如果有效,则到达下一步;
7.服务器重新响应第2步所提交的原始请求,并判断该请求所访问的程序资源是否在你的权限范围内,如果你有权访问,请求将得到正确的执行并返回结果。否 则,你将收到一个HTTP 403错误,这意味着你被禁止访问。
3、访问控制过程:
1. 从SecurityContext中取出已经认证过的Authentication(包括权限信息);
2. 通过反射机制,根据目标安全对象和“配置属性”得到访问目标安全对象所需的权限;
3. AccessDecisionManager根据Authentication的授权信息和目标安全对象所需权限做出是否有权访问的判断。如果无权访问,Acegi将抛出AccessDeniedException异常,否则到下一步;
4. 访问安全对象并获取结果(返回值或HTTP响应);
5.AbstractSecurityInterceptor可以在结果返回前进行处理:更改结果或抛出异常。
三、spring相关jar概览
security-core 用户、token、session等的维护
UserDetailsService TokenService SessionRegistry AbstractAuthenticationToken
security-oauth2 对oauth2的支持
security-config 资源权限的配置
SecurityConfigurer HttpSecurityBuilder
security-web 使用filter等与容器相融合
DefaultRedirectStrategy DefaultSecurityFilterChain
oauth2基本过程:重定向到server、auth、访问token、身份数据插入Spring Security context
四、使用
1、依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2、代码
@EnableWebSecurity
默认配置
1、访问应用中的每个URL都需要进行验证
2、生成一个登陆表单
3、允许用户使用username和password来登陆
4、允许用户注销
5、CSRF攻击拦截
6、 Session Fixation攻击
7、 安全Header集成
extends WebSecurityConfigurerAdapter
@Bean
public UserDetailsService userDetailsService() {
return new CustomUserDetailsService();
}
@Bean
public PasswordEncoder passwordEncoder(){
return new Md5PasswordEncoder();
}
@Bean
public AuthenticationProvider authenticationProvider(){
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService());
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//auth.userDetailsService(userDetailsService());
auth.authenticationProvider(authenticationProvider());
}
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**").
// 根据request验证
authorizeRequests()
.antMatchers("/", "/login**", "/webjars/**")
.permitAll()
// 其他的 <intercept-url pattern="/**" access="authenticated"/>
.anyRequest()
.authenticated().and()
.exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/")).and()
// 允许所有人logout
.logout().logoutSuccessUrl("/").permitAll().and()
// csrf支持
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
// 注册sso的filter
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
}
五、sso
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
security:
oauth2:
client:
clientId: 233668646673605
clientSecret: 33b17e044ee6a4fa383f46ec6e28ea1d
accessTokenUri: https://graph.facebook.com/oauth/access_token
userAuthorizationUri: https://www.facebook.com/dialog/oauth
tokenName: oauth_token
authenticationScheme: query
clientAuthenticationScheme: form
resource:
userInfoUri: https://graph.facebook.com/me
六、内部实现细节
1、安全在web中使用filter,在app中使用aop,本质是在正常的请求前后加点料
2、@EnableWebSecurity 内部会注入一个springSecurityFilterChain
springSecurityFilterChain内部根据url来配置对应的filter
3、HttpSecurity用来 配置url、filter、对应的权限
4、AuthenticationManagerBuilder 配置验证的方式,比如UserDetailsService、passwordEncoder等
5、sso的实现:添加了一个filter OAuth2ClientAuthenticationProcessingFilter
6、OAuth2ClientAuthenticationProcessingFilter=AuthorizationCodeResourceDetails(获取token)+ResourceServerProperties(获取user信息)
七、附录
oauth2.0过程:
1》client app 向server请求临时令牌
2》获得后,带着临时token去server验证用户名、密码 # auth url
3》验证后server 回调client app获得授权
4》client app用临时token获得 acess token # token url
5》用access token获取用户信息# user url
application.xml中的配置
userAuthorizationUri auth url
accessTokenUri token url
userInfoUri user url
评论