SpringSecurity:helloworld
作者:互联网
5.20
Spring Security
Spring 是非常流行和成功的 Java 应用开发框架,Spring Security 正是 Spring 家族中的成员。Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。
正如你可能知道的关于安全方面的两个主要区域是“认证”和“授权”(或者访问控制),一般来说,Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分,这两点也是 Spring Security 重要核心功能。
- 用户认证指的是:验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。通俗点说就是系统认为用户是否能登录。
- 用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。通俗点讲就是系统判断用户是否有权限去做某些事情。
特点
SpringSecurity 特点:
-
和 Spring 无缝整合。
-
全面的权限控制。
-
专门为Web 开发而设计。
-
旧版本不能脱离Web 环境使用。
-
新版本对整个框架进行了分层抽取,分成了核心模块和Web 模块。单独引入核心模块就可以脱离Web 环境。
-
-
重量级。
Shiro
Apache 旗下的轻量级权限控制框架。
特点:
- 轻量级。Shiro 主张的理念是把复杂的事情变简单。针对对性能有更高要求的互联网应用有更好表现。
- 通用性。
- 好处:不局限于Web 环境,可以脱离Web 环境使用。
- 缺陷:在Web 环境下一些特定的需求需要手动编写代码定制。
比较
相对于 Shiro,在 SSM 中整合 Spring Security 都是比较麻烦的操作,所以,Spring Security 虽然功能比 Shiro 强大,但是使用反而没有 Shiro 多(Shiro 虽然功能没有Spring Security 多,但是对于大部分项目而言,Shiro 也够用了)。自从有了 Spring Boot 之后,Spring Boot 对于 Spring Security 提供了自动化配置方案,可以使用更少的配置来使用 Spring Security。
- SSM + Shiro
- Spring Boot/Spring Cloud + Spring Security
入门案例
-
引入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
-
编写controller
@RestController @RequestMapping("test") public class TestController { @GetMapping("add") public String add(){ return "hello security"; } }
-
直接访问
-
用户名和密码
SpringSecurity默认用户名user,而密码会打印在控制台。
Using generated security password: 4bb96c68-fe1f-4cc4-970f-7d4a0931dfd8
SpringSevurity本质上是一个过滤器链
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFil ter
org.springframework.security.web.context.SecurityContextPersistenceFilter org.springframework.security.web.header.HeaderWriterFilter org.springframework.security.web.csrf.CsrfFilter org.springframework.security.web.authentication.logout.LogoutFilter org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter org.springframework.security.web.savedrequest.RequestCacheAwareFilter org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter org.springframework.security.web.authentication.AnonymousAuthenticationFilter org.springframework.security.web.session.SessionManagementFilter org.springframework.security.web.access.ExceptionTranslationFilter org.springframework.security.web.access.intercept.FilterSecurityInterceptor
每一个过滤器都放行才能正常访问!
几个重要的过滤器
FilterSecurityInterceptor
本质上过滤器是拦截器的
是一个方法级的权限过滤器, 基本位于过滤链的最底部
- 该拦截器实现了Filter接口。
- 主要所用是判断其他过滤器是否放行?
ExceptionTranslationFilter
是个异常过滤器,用来处理在认证授权过程中抛出的异常
UsernamePasswordAuthenticationFilter
对/login 的 POST 请求做拦截,校验表单中用户名,密码。
过滤器加载过程
-
需要配置一个过滤器(
DelegatingFilterProxy
) -
通过
WebApplicationContext
中获取FilterChainProxy
的过滤器。 -
FilterChainProxy
中,通过doFilterInternal()
方法获取List,然后使用doFilter()方法继续后续步骤。
两个重要接口(两个重要极限,既视感。。)
- UserDetailsService
- PasswordEncoder
UserDetailsService
当什么也没有配置的时候,账号和密码是由 Spring Security 定义生成的。而在实际项目中账号和密码都是从数据库中查询出来的。 所以我们要通过自定义逻辑控制认证逻辑。
查询用户名和密码的过程
- 创建类并继承
UsernamePasswordAuthenticationFilter
并重写三个方法 - 创建类实现UserDetailService编写查询过程,返回User对象。该User对象由框架提供
PasswordEncoder
用于对明文密码的加密!
一般用于返回User对象密码的加密
BCryptPasswordEncoder 是 Spring Security 官方推荐的密码解析器,平时多使用这个解析器。
BCryptPasswordEncoder 是对bcrypt 强散列方法的具体实现。是基于 Hash 算法实现的单向加密。可以通过 strength 控制加密强度,默认 10.
设置登录的用户名密码
- 通过配置文件
- 通过配置类
- 自定义实现类
通过配置文件
spring:
security:
user:
name: hello
password: hello
通过配置类
@Configuration
public class UserConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//对密码进行加密
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
String encode = bCryptPasswordEncoder.encode("123456");
auth.inMemoryAuthentication().withUser("boerk").password(encode).roles("admin");
}
//需要向Spring容器中注入PasswordEncoder对象,否则会报错
//这里通过一个BeanConfig实现
}
如果明文输入密码,则使用{noop}123456
auth.inMemoryAuthentication().withUser("boerk").password("{noop}123456").roles("admin");
通过自定义实现类
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String encode = passwordEncoder.encode("123456");
UserDetails build = User.withUsername("zhangsan").password(encode).authorities("admin").build();
return build;
}
}
或者!
//实现类
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
List<GrantedAuthority> auths = AuthorityUtils.createAuthorityList("role");
return new User("boerk",new BCryptPasswordEncoder().encode("123456"),auths);
}
}
//config
@Configuration
public class UserConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
}
}
如果使用PasswordEncoder的实现类对象,则必须向容器注入PasswordEncoder
@Configuration
public class BeanConfig {
@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
总结:用户认证的方式
- 通过配置文件实现
- 通过配置类,继承WebSecurityConfigureAdapter接口,重写configure方法,通过该方法入参对象设置。
- 通过自定义实现类的方式,实现UserDetailsService,重写loadUserByUserName,通过User对象设置。
标签:web,Spring,springframework,SpringSecurity,helloworld,org,security,Security 来源: https://www.cnblogs.com/Boerk/p/16294078.html