Spring Security(官网地址:https://spring.io/projects/spring-security)是Spring家族的安全框架
依赖配置
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
SecurityConfig
使用Spring Security进行安全管理需要使SecurityConfig继承WebSecurityConfigurerAdapter类,并且使用HttpSecurity的一些安全策略进行配置。
• authorizeRequests:配置一些资源或链接的权限认证。
• antMatchers:配置哪些资源或链接需要被认证。
• permitAll:设置完全允许访问的资源和链接。
• hasRole:配置需要认证的资源或链接的角色。需要注意,若这里需要配置权限为USER,则用户需要拥有权限ROLE_USER,这就是初始化脚本中权限内容修改的原因。
• formLogin:设置form表单提交配置。
• loginPage:设置一个自定义的登录页面URL。
• failureUrl:设置一个自定义的登录失败的URL。
• successForwardUrl:设置一个登录成功后自动跳转的URL。
• accessDeniedPage:设置拒绝访问的URL。
• logoutSuccessUrl:设置退出登录的URL。
@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private RoleRepository roleRepository; @Autowired private MyUserDetailsService myUserDetailsService; @Override protected void configure(HttpSecurity httpSecurity) throws Exception { //配置资源文件 其中/css/**,/index可以任意访问,/select需要USER权限,/delete需要ADMIN权限 httpSecurity .authorizeRequests() .antMatchers("/css/**", "/index").permitAll() .antMatchers("/select").hasRole("USER") .antMatchers("/delete").hasRole("ADMIN"); //动态加载数据库中角色权限 List<Role> roleList = roleRepository.findAll(); for (Role role : roleList) { List<Menu> menuList = role.getMenuList(); for (Menu menu : menuList) { //在SpringSecurity校验权限的时候,会自动将权限前面加ROLE_,所以我们需要 将我们数据库中配置的ROLE_截取掉。 String roleName = role.getRoleName().replace("ROLE_", ""); String menuName = "/" + menu.getMenuName(); httpSecurity .authorizeRequests() .antMatchers(menuName) .hasRole(roleName); } } //配置登录请求/login 登录失败请求/login_error 登录成功请求/ httpSecurity .formLogin() .loginPage("/login") .failureUrl("/login_error") .successForwardUrl("/"); //登录异常,如权限不符合 请求/401 httpSecurity .exceptionHandling().accessDeniedPage("/401"); //注销登录 请求/logout httpSecurity .logout() .logoutSuccessUrl("/logout"); } @Bean public static NoOpPasswordEncoder passwordEncoder() { return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance(); } //根据用户名密码实现登录 @Autowired public void configureGlobal(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { authenticationManagerBuilder .inMemoryAuthentication() //.passwordEncoder(new BCryptPasswordEncoder()) .withUser("test").password("123").roles("USER") .and() .withUser("admin").password("123").roles("ADMIN", "USER"); authenticationManagerBuilder.userDetailsService(myUserDetailsService); } }
MyUserDetailsService
使用数据库认证用户需要自定义一个类来实现UserDetailsService重写loadUserByUsername方法进行认证授权
@Service public class MyUserDetailsService implements UserDetailsService { @Autowired private UserRepository userRepository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userRepository.findByUserName(username); if (user == null) { throw new UsernameNotFoundException("用户不存在!"); } List<SimpleGrantedAuthority> simpleGrantedAuthorities = new ArrayList<>(); for (Role role : user.getRoleList()) { simpleGrantedAuthorities.add(new SimpleGrantedAuthority(role.getRoleName())); } return new org.springframework.security.core.userdetails.User(user.getUserName(), user.getPassWord(), simpleGrantedAuthorities); } }
Controller
@Controller @Api(tags = "TestSecurityController") public class TestSecurityController { private static final Logger log = LoggerFactory.getLogger(TestSecurityController.class); @RequestMapping({"/", "/index"}) public String index() { return "index"; } @RequestMapping("/select") public String select() { return "select"; } @RequestMapping("/delete") public String delete() { return "delete"; } @RequestMapping("/login") public String login() { return "login"; } @RequestMapping("/login_error") public String login_error(Model model) { model.addAttribute("login_error", "用户名或密码错误"); return "login"; } @RequestMapping("/logout") public String logout(Model model) { model.addAttribute("login_error", "注销成功"); return "login"; } @RequestMapping("/401") public String error() { return "401"; } }
参考来源:Spring Boot 2实战之旅-7.2 使用Spring Security
源码:https://gitee.com/caoyeoo0/xc-springboot/tree/springSecurity/