# springboot_springsecurity **Repository Path**: stefanpy/springboot_springsecurity ## Basic Information - **Project Name**: springboot_springsecurity - **Description**: springboot 整合spring security - **Primary Language**: Java - **License**: Not specified - **Default Branch**: dev - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 2 - **Created**: 2018-05-18 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README springboot 整合 Spring Security 第一步:加入依赖 ``` org.springframework.boot spring-boot-starter-security ``` 一旦引入这个依赖,spring boot项目就默认开启了 security的默认保护。访问任何请求都会跳转到/login ,默认显示一个登录页面,但是我们并不知道用户名和密码。 用户名默认是user,密码是加密的 在运行后台可以找到,默认是打印到后来的。 第二步:java 配置类 ``` package com.young.security.mysecurity.config; import com.young.security.mysecurity.security.MyUserDetailService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl; import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository; import javax.sql.DataSource; /** * Create by stefan * Date on 2018-05-17 21:23 * Convertion over Configuration! */ @EnableWebSecurity @EnableGlobalMethodSecurity(securedEnabled = true,jsr250Enabled = true,prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private DataSource dataSource; @Autowired private MyUserDetailService myUserDetailService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //1.启用内存用户存储 // auth.inMemoryAuthentication() // .withUser("xfy").password(passwordEncoder().encode("1234")).roles("ADMIN").and() // .withUser("tom").password(passwordEncoder().encode("1234")).roles("USER"); //2.基于数据库表进行验证 // auth.jdbcAuthentication().dataSource(dataSource) // .usersByUsernameQuery("select username,password,enabled from user where username = ?") // .authoritiesByUsernameQuery("select username,rolename from role where username=?") // .passwordEncoder(passwordEncoder()); //3.配置自定义的用户服务 auth.userDetailsService(myUserDetailService); } @Override protected void configure(HttpSecurity http) throws Exception { http.formLogin().loginPage("/signIn").loginProcessingUrl("/user/userLogin") //自定义登录页面、登录请求路由 .and() .logout().logoutSuccessUrl("/signIn")// 设置登出,登出成功后跳转到登录页面 .and() .authorizeRequests() //开始请求的配置 .antMatchers("/signIn","/hello").permitAll() // premitAll()不做拦截 .antMatchers("/index").authenticated() //authenticated() 必须登录后可见 .antMatchers("/demo").permitAll() .antMatchers("/admin/**","/add").hasRole("ADMIN") //有ADMIN角色 .regexMatchers("/admin1/.*").access("hasRole('ADMIN') or hasRole('ADMIN1')") .anyRequest().authenticated() .and() .requiresChannel().antMatchers("/add").requiresSecure()//https://127.0.0.1:8443/add 将http转为https .and() .rememberMe().tokenValiditySeconds(2419200).tokenRepository(persistentTokenRepository()).alwaysRemember(true);// 启用记住我 } // 记住我,将用户信息存入数据库 @Bean public PersistentTokenRepository persistentTokenRepository() { JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl(); tokenRepository.setDataSource(dataSource); //tokenRepository.setCreateTableOnStartup(true); return tokenRepository; } //注册密码加密处理器 @Bean public static PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } } ``` **自定义UserDetailsService** ``` package com.young.security.mysecurity.security; import com.young.security.mysecurity.pojo.Role; import com.young.security.mysecurity.pojo.User; import com.young.security.mysecurity.repository.RoleRepository; import com.young.security.mysecurity.repository.UserRepository; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; /** * Create by stefan * Date on 2018-05-17 22:49 * Convertion over Configuration! */ @Component @Slf4j public class MyUserDetailService implements UserDetailsService { @Autowired private PasswordEncoder passwordEncoder; @Autowired UserRepository userRepository; @Autowired private RoleRepository roleRepository; @Override public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException { User user = userRepository.findByUsername(name); if (user==null){ throw new AuthenticationCredentialsNotFoundException("authError"); } log.info("{}",user); List role = roleRepository.findByUsername(name); log.info("{}",role); List authorities = new ArrayList<>(); role.forEach(role1 -> authorities.addAll(AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_"+role1.getRolename()))); log.info("{}",authorities); return new org.springframework.security.core.userdetails.User(user.getUsername(),user.getPassword(),authorities); } } ``` ### 使用注解保护 #### 开启注解 ``` @EnableGlobalMethodSecurity(securedEnabled = true,jsr250Enabled = true,prePostEnabled = true) ``` #### 注解示意: ``` @Secured({"ADMIN","ADMIN1"}) @RolesAllowed({"ADMIN","ADMIN1"}) 使用方式相似,RolesAllowed更正式 ``` ``` @PreAuthorize("hasRole('ADMIN') AND hasRole('ADMIN1')") 的string参数是一个SpEL表达式 @PreAuthorize("hasRole('ADMIN') and #user.username.length() <=6") 可获得参数 @PostAuthorize("returnObject.username == principal.username") 可获得返回值 过滤方法 @PostFilter("hasRole('ADMIN') || filterObject.username == principal.username") 这个可直接获得方法的返回值列表的单个元素filterObject,不需要加# @PreFilter("hasRole('ADMIN') || #filterObject.endsWith('admin')") 加#filterObject可获得传入参数列表的单个元素 ``` 视图保护(Thymeleaf) 第一步:引入依赖 ``` org.springframework.boot spring-boot-starter-thymeleaf org.thymeleaf.extras thymeleaf-extras-springsecurity4 ``` 第二步:在视图页声明: ``` ``` 第三步使用: ```
hello someone !
会员admin可见
会员admin\ADMIN1可见
admin中心 admin1中心 ``` 个人详细笔记整理: [让Spring Security 来保护你的Spring Boot项目吧](https://www.jianshu.com/p/6df285f30a79) **参考资料:** - 书籍:Spring实战(第4版) 第9章和第14章 - [Spring Security 参考手册](https://springcloud.cc/spring-security-zhcn.html) - [初识 Spring Security](https://note.youdao.com/) - [程序猿DD的Spring Security学习笔记](http://blog.didispace.com/tags/Spring-Security/) *Spring Security 的使用才刚刚开始。*