使用场景:用于访问权限的限制于管理
过程:通过用户名查询密码和角色,校验密码和判断该url是否允许该角色访问
引用Security准备
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.3.1.tmp</version> </dependency>
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> <version>8.0.13</version> </dependency>
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.8</version> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
<dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>2.0.3</version> </dependency>
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.75</version> </dependency>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
@Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired private UserService userService; @Autowired private LoginFailHandler loginFailHandler; @Autowired private LoginSuccessHandler loginSuccessHandler; @Autowired private ForbidHandler forbidHandler;
@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userService); }
@Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable();
http.formLogin() .loginPage("/login.html") .loginProcessingUrl("/login") .successHandler(loginSuccessHandler) .failureHandler(loginFailHandler);
http.exceptionHandling().accessDeniedHandler(forbidHandler); http.logout() .logoutUrl("/logout") .logoutSuccessUrl("/test/toLogin"); http.authorizeRequests() .antMatchers("/login.html").permitAll() .anyRequest().authenticated(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
@Service public class UserService implements UserDetailsService {
@Autowired private SysUserDao sysUserDao; @Autowired private PasswordEncoder passwordEncoder;
@Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("username", username); List<SysUser> users = sysUserDao.selectList(queryWrapper); if (users.size() < 0) { throw new UsernameNotFoundException("未找到用户信息"); }
List<GrantedAuthority> authorities = new ArrayList<>(); for (SysUser sysUser:users) { String role = sysUser.getRole(); authorities.add(new SimpleGrantedAuthority(role));
}
SysUser user = users.get(0); return new User(user.getUsername(), passwordEncoder.encode(user.getPassword()), authorities); } }
|
登录成功Handler
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Component public class LoginSuccessHandler implements AuthenticationSuccessHandler {
@Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { response.setContentType("application/json;charset=UTF-8"); response.setCharacterEncoding("utf-8"); PrintWriter printWriter = response.getWriter(); printWriter.write(ReturnDto.ok().toString()); printWriter.flush(); printWriter.close(); } }
|
登录失败Handler
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Component public class LoginFailHandler implements AuthenticationFailureHandler {
@Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { response.setContentType("application/json;charset=UTF-8"); response.setCharacterEncoding("utf-8"); PrintWriter printWriter = response.getWriter(); printWriter.write(ReturnDto.error("登录失败").toString()); printWriter.flush(); printWriter.close(); } }
|
无访问权限Handler
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Component public class ForbidHandler implements AccessDeniedHandler {
@Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { response.setContentType("application/json;charset=UTF-8"); response.setCharacterEncoding("utf-8"); PrintWriter printWriter = response.getWriter(); printWriter.write(ReturnDto.error("无查看权限").toString()); printWriter.flush(); printWriter.close(); } }
|
配置类方式配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @RestController @RequestMapping("/test") public class SecurityController {
@GetMapping("/toLogin") public void toLogin(HttpServletResponse response) throws IOException { response.sendRedirect("login.html"); } @GetMapping("/test1") public ReturnDto TestOnly(){ return ReturnDto.ok("访问成功"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
@Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired private UserService userService; @Autowired private LoginFailHandler loginFailHandler; @Autowired private LoginSuccessHandler loginSuccessHandler; @Autowired private ForbidHandler forbidHandler;
@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userService); }
@Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable();
http.formLogin() .loginPage("/login.html") .loginProcessingUrl("/login") .successHandler(loginSuccessHandler) .failureHandler(loginFailHandler);
http.exceptionHandling().accessDeniedHandler(forbidHandler); http.logout() .logoutUrl("/logout") .logoutSuccessUrl("/test/toLogin"); http.authorizeRequests() .antMatchers("/login.html").permitAll()
.anyRequest().authenticated(); } }
|
注解方式配置
1
| @EnableGlobalMethodSecurity(securedEnabled = true)
|
1 2
| @Secured({"ROLE_admin","ROLE_user"})
|
1 2 3
| @PreAuthorize("hasAnyAuthority('admin')") @PreAuthorize("hasAnyRole('ROLE_admin')")
|
1 2 3
| @PostAuthorize("hasAnyAuthority('admin')") @PostAuthorize("hasAnyRole('ROLE_admin')")
|
1 2
| @PreFilter("filterObject.key == '正'")
|
1 2
| @PostFilter("filterObject.key == '正'")
|
代码例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| @RestController @RequestMapping("/test") public class SecurityController {
@Autowired private TestService testService;
@GetMapping("/toLogin") public void toLogin(HttpServletResponse response) throws IOException { response.sendRedirect("login.html"); } @GetMapping("/test1")
public ReturnDto TestOnly(){ return ReturnDto.ok("成功"); }
@GetMapping("/testPostFilter") public ReturnDto testPostFilter(){ return ReturnDto.ok(testService.testPostFilter()); }
@GetMapping("/testPreFilter") public ReturnDto testPreFilter(){ List<TestEntity> testEntities = new ArrayList<>(); testEntities.add(new TestEntity("正","数据1")); testEntities.add(new TestEntity("反","数据1(反)")); testEntities.add(new TestEntity("反","数据2(反)")); testEntities.add(new TestEntity("正","数据2")); testEntities.add(new TestEntity("反","数据3(反)")); testEntities.add(new TestEntity("正","数据3")); return ReturnDto.ok(testService.testPreFilter(testEntities)); }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Service public class TestService {
@PostFilter("filterObject.key == '正'") public List<TestEntity> testPostFilter(){ List<TestEntity> testEntities = new ArrayList<>(); testEntities.add(new TestEntity("正","数据1")); testEntities.add(new TestEntity("反","数据1(反)")); testEntities.add(new TestEntity("反","数据2(反)")); testEntities.add(new TestEntity("正","数据2")); testEntities.add(new TestEntity("反","数据3(反)")); testEntities.add(new TestEntity("正","数据3")); return testEntities; }
@PreFilter("filterObject.key == '正'") public List<TestEntity> testPreFilter(List<TestEntity> testEntities){ return testEntities; } }
|