二、简单使用org.springframework.boot spring-boot-starter-parent2.2.1.RELEASE 4.0.0 com.darren.test security-test1.0-SNAPSHOT UTF-8 UTF-8 2.2.1.RELEASE 1.8 org.springframework.boot spring-boot-starter-testtest ${spring.boot.version} org.springframework.boot spring-boot-starter-web${spring.boot.version} org.springframework.boot spring-boot-starter-security${spring.boot.version} org.springframework.boot spring-boot-maven-plugin
需要手动实现或继承以下三个类:
1. UserDetailsService该接口返回UserDetails对象,返回用户名、密码、权限等用户基本信息,实现类主要实现相关信息的获取。
@Service
public class UserDetailServiceImpl implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
List auths = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
return new User("darren", "123", auths);
}
}
UserDetails为接口对象,需要进行实现。框架提供的实现类User基本够用。
GrantedAuthority为security提供的用于存储角色或权限信息的实体类,角色必须以“ROLE_”开头,权限不需要。
2. PasswordEncoder密码加密接口实现,这里密码不加密。
public class NoEncryptPasswordEncoder implements PasswordEncoder {
@Override
public String encode(CharSequence charSequence) {
return (String) charSequence;
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return s.contentEquals(charSequence);
}
}
3. WebSecurityConfigurerAdapter
该类为抽象类,提供继承以自定义安全配置。
@Configuration
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailServiceImpl userDetailService;
@Bean
public PasswordEncoder passwordEncoder() {
return new NoEncryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 自定义登录页面、登录接口、成功跳转,适用前后端不分离项目
http.formLogin().loginPage("/login.html").loginProcessingUrl("/auth/login").defaultSuccessUrl("/test/home").permitAll()
// 放行路径
.and().authorizeRequests().antMatchers("/test/test1", "/test/test2").permitAll()
// 登录管控路径
.and().authorizeRequests().anyRequest().authenticated()
// 关闭csrf防护
.and().csrf().disable();
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
简单说明:
(1)formLogin().loginPage("/login.html")自定义登录页面,不定义时使用默认页面。
(2)formLogin().loginProcessingUrl("/auth/login")定义登录路径,无需编写相关控制器,由框架配置。
(3).and()用于回到HttpSecurity,继续往后配置。
(4).authorizeRequests().antMatchers("/test/test1", "/test/test2"):访问路径在括号范围内。
(5).authorizeRequests().anyRequest():所有路径
(6).permitAll()放行
(7).authenticated()需要登录
(8)权限管控另有:hasRole()、hasAnyRole()、hasAuthority()、hasAnyAuthority(),分别是有某个角色、有括号中任意一个角色、有某个权限、有括号中的任意一个权限
附:
自定义的简单页面
登录页面
请登录:
三、异常处理
http.exceptionHanding().xxx
四、注解使用 1. @Secured(1)含义:用户具有某个角色,可以访问方法。
(2)配置类或程序启动类上方添加@EnableGlobalMethodSecurity(securedEnabled = true),开启安全注解。
(3)在controller方法上使用该注解。例:@Secured("ROLE_ADMIN", "ROLE_GUEST")
(4)userDetailService中设置用户具体角色
2.@PreAuthorize(1)方法执行之前进行权限检查
(2)配置类或程序启动类上方添加@EnableGlobalMethodSecurity(prePostEnabled = true),开启安全注解。
(3)在controller方法上使用该注解。例:
@PreAuthorize("hasAuthority('query')")
@PreAuthorize("hasAnyAuthority('query', 'update')")
// 这里的hasRole/hasAnyRole不同于配置类,角色名需带上ROLE_前缀
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_GUEST')")
(4)userDetailService中设置用户具体权限
3.@PostAuthorize(使用低频)方法执行后进行过滤,适合验证带有返回值的权限,其余同2。
4.@PostFilter(使用低频)(1)在方法执行结束之后,对返回数据进行过滤,只返回满足条件的数据。
(2)filterObject是返回数据对象:
@PostFilter("filterObject.username == 'admin1'")
public List
在循环结束后list包含username为admin1和admin2的记录。经过过滤最终只返回username为admin1的记录。
5.@PreFilter(使用低频)(1)通过权限验证之后,方法执行之前,对传入数据进行过滤,只接收满足条件的数据。
(2)例:传入的list中只取id能被2整除的数据:@PreFilter(value = "filterObject.id % 2 == 0")
五、用户注销http.logout().logout("/logout").logoutSuccessUrl("/test/out").permitAll();
与配置登录的方式差不多。



