1.Spring Security 能干什么
Spring Security 是一个功能强大且高度可定制的身份验证和访问控制框架。 Spring Security 是一个专注于为 Java 应用程序提供身份验证和授权的框架。 与所有 Spring 项目一样,Spring Security 的真正强大之处在于它可以轻松扩展以满足自定义要求
2.认证配置
@Configuration //springboot开启是扫描的类
@EnableWebSecurity//开启springsecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
}
@Configuration
@EnableWebSecurity //开启springsecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
SysUserService userService;
@Override
public void configure(WebSecurity web) {
// 设置不拦截规则
web.ignoring().antMatchers("/login", "/images/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/*", "/**").permitAll()
.antMatchers("/**").authenticated() // 指定所有的请求都需登录
.anyRequest().authenticated()
.and()
.cors().and().csrf().disable()
// 自定义登录页面
.formLogin()
.loginPage("/login") // 指定登录页面
.loginProcessingUrl("/signin") // 执行登录操作的 URL
.usernameParameter("username") // 用户请求登录提交的的用户名参数
.passwordParameter("password") // 用户请求登录提交的密码参数
.failureHandler(this.authenticationFailureHandler()) // 定义登录认证失败后执行的操作
.successHandler(this.authenticationSuccessHandler()); // 定义登录认证曾工后执行的操作
// 自定义注销
http.logout().logoutUrl("/signout") // 执行注销操作的 URL
.logoutSuccessUrl("/login") // 注销成功后跳转的页面
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID");
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("*"));
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
/**
* 登录认证配置
*/
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(this.userDetailsService())
.passwordEncoder(new BCryptPasswordEncoder());
}
/**
* 使用自定义的登录密码加密规则,需继承 LLgRi7cWeUUu5zpB7dekZFapB2XdRCvM4N
*/
@Bean(name = "myMessageDigestPasswordEncoder")
public PasswordEncoder messageDigestPasswordEncoder() {
return new MyMessageDigestPasswordEncoder("md5");
}
/**
* 使用自定义的登录认证失败处理类,需继承 AuthenticationFailureHandler
*/
@Bean(name = "authenticationFailureHandlerImpl")
public AuthenticationFailureHandler authenticationFailureHandler() {
return new AuthenticationFailureHandlerImpl();
}
/**
* 使用自定义的登录认证成功处理类,需继承 AuthenticationSuccessHandler
*/
@Bean(name = "authenticationSuccessHandlerImpl")
public AuthenticationSuccessHandler authenticationSuccessHandler() {
return new AuthenticationSuccessHandlerImpl();
}
@Bean(name = "userDetailsServiceImpl")
public UserDetailsService userDetailsService() {
return new UserDetailsServiceImpl();
}
// 表达式控制器
@Bean(name = "expressionHandler")
public DefaultWebSecurityExpressionHandler webSecurityExpressionHandler() {
return new DefaultWebSecurityExpressionHandler();
}
@Bean(BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
配置之后当我们请求/login,提交表单表单的中用户名和密码的name 时username和password,spring 会拦截并校验用户名和密码。
UserDetailsService是查询数据库中的用户和用户所对应的角色
public class UserDetailsServiceImpl implements UserDetailsService {
@Resource
private SysUserService sysUserService;
@Autowired
private SysUserRoleService sysUserRoleService;
@Autowired
private SysRoleService sysRoleService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if (StringUtils.isEmpty(username)) {
throw new BadCredentialsException("用户名不能为空");
}
UserDetails userDetails = null;
// 根据用户名从数据库查询用户信息,根据自己的业务规则去写
SysUser user = (SysUser) sysUserService.findByUserName(username);
if (user == null) {
throw new BadCredentialsException("用户名不存在");
}
//获取用户角色列表
List<SysUserRole> surList = sysUserRoleService.getUserRoleByUserId(user.getId());
String roles = "";
for (SysUserRole sur : surList) {
SysRole sr = (SysRole) sysRoleService.findById(sur.getRoleId());
roles += "ROLE_" + sr.getRole() + ",";
}
List<GrantedAuthority> grantedAuthorityList = AuthorityUtils.createAuthorityList(roles.substring(0, roles.length() - 1));
userDetails = new User(user.getUsername(), user.getPassword(), // 数据库中存储的密码
true, // 用户是否激活
true, // 帐户是否过期
true, // 证书是否过期
true, // 账号是否锁定
grantedAuthorityList); // 用户角色列表,必须以 ROLE_ 开头
return userDetails;
}
这样当校验成功或失败后security 将吧控制权交到 AuthenticationSuccessHandler,AuthenticationFailureHandler。我们可以实现个类做成功或失败的处理
3.资源访问控制
假设有个列表页面,操作权限要分给不同的人。后端可以使用注解,前端可以使用springsecurity标签
@EnableGlobalMethodSecurity(prePostEnabled=true)
@PreAuthorize("hasAuthority('list')")
<sec:authorize access="hasAuthority('addArticle')"></sec>
引用文档
https://docs.spring.io/spring-security/reference/servlet/architecture.html
分享到: