springboot11-security02FromDB 权限管理(用户信息和角色信息保存在数据库)
<h4>场景</h4>
<h4>代码</h4>
springboot+springsecurity+mysql(jpa)实现:
1.pom依赖:
1 <!-- security --> 2 <dependency> 3 <groupId>org.springframework.boot</groupId> 4 <artifactId>spring-boot-starter-security</artifactId> 5 </dependency> 6 <dependency> 7 <groupId>org.springframework.boot</groupId> 8 <artifactId>spring-boot-starter-thymeleaf</artifactId> 9 </dependency> 10 11 <!--jpa--> 12 <dependency> 13 <groupId>org.springframework.boot</groupId> 14 <artifactId>spring-boot-starter-data-jpa</artifactId> 15 </dependency> 16 <!--mysql--> 17 <dependency> 18 <groupId>mysql</groupId> 19 <artifactId>mysql-connector-java</artifactId> 20 </dependency>
2.application配置:
1 spring.thymeleaf.prefix=classpath:/page/ 2 3 #mysql连接地址 4 spring.datasource.url=jdbc:mysql://localhost:3307/springboot_test 5 #mysql用户名和密码 6 spring.datasource.username=root 7 spring.datasource.password=root 8 #driver驱动 9 spring.datasource.driver-class-name=com.mysql.jdbc.Driver 10 #show sql 11 spring.jpa.show-sql=true 12 # Hibernate ddl auto (create, create-drop, update) 13 #### hibernate的ddl-auto=update配置表名,数据库的表和列会自动创建(根据Java实体) 14 spring.jpa.hibernate.ddl-auto=update 15 # 方言 16 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
3.连接数据库:db->bean->dao->service
public interface UserDao extends JpaRepository<User, Long>{ User findByUserName(String userName); User findByUserNameAndPassword(String userName, String password); }
@Service public class UserService { @Autowired private UserDao userDao; public User findById(Long id){ return userDao.findOne(id); } public User findByUserName(String userName){ return userDao.findByUserName(userName); } public User login(String userName, String password){ return userDao.findByUserNameAndPassword(userName, password); } public List<User> userList(){ return userDao.findAll(); } }
实体类User
@Entity @Table(name = "user") public class User implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String userName; private String password; private String pwdBak; private String role; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } @Override public Collection<? extends GrantedAuthority> getAuthorities() { List<SimpleGrantedAuthority> auths = new ArrayList<>(); auths.add(new SimpleGrantedAuthority(this.getRole())); return auths; } public String getPassword() { return password; } @Override public String getUsername() { return this.userName; } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } public void setPassword(String password) { this.password = password; } public String getPwdBak() { return pwdBak; } public void setPwdBak(String pwdBak) { this.pwdBak = pwdBak; } public String getRole() { return role; } public void setRole(String role) { this.role = role; } @Override public String toString() { return "User{" + "id=" + id + ", userName='" + userName + '\'' + ", password='" + password + '\'' + ", pwdBak='" + pwdBak + '\'' + ", role='" + role + '\'' + '}'; } }
4.websecurity配置:
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true)//开启进入Controller之前,检验权限。这个注解配置后,Controller中的@PreAuthorize("hasAnyAuthority('ADMIN')")才会生效 public class WebSecurityConfig extends WebSecurityConfigurerAdapter{ @SuppressWarnings("SpringJavaAutowiringInspection") @Autowired private MyUDService myUDService; @Bean @Override protected AuthenticationManager authenticationManager() throws Exception { return super.authenticationManager(); } @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity.authorizeRequests() .antMatchers("/", "/login", "/err/*").permitAll() //无需验证权限 .anyRequest().authenticated() //其他地址的访问均需验证权限 .and().formLogin().loginPage("/login").defaultSuccessUrl("/home").permitAll()//指定登录页是"/login" //登录成功后默认跳转到"/home" .and().logout().logoutSuccessUrl("/login").permitAll(); //退出登录后的默认url是"/login" } /** * 全局配置 * @param builder * @throws Exception */ @Autowired public void configure(AuthenticationManagerBuilder builder) throws Exception { builder .userDetailsService(myUDService) .passwordEncoder(this.passwordEncoder()); } /** * 设置用户密码的加密方式:MD5加密 * @return */ @Bean public PasswordEncoder passwordEncoder(){ PasswordEncoder pe = new PasswordEncoder() {//自定义密码加密方式 //加密 @Override public String encode(CharSequence charSequence) { return MD5Util.encode((String)charSequence); } //校验密码 @Override public boolean matches(CharSequence charSequence, String s) { return MD5Util.encode((String)charSequence).equals(s); } }; return pe; } }
5.用户权限查询类UserDetailsService:
@Component public class MyUDService implements UserDetailsService { @Autowired private UserService userService; @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { User user = userService.findByUserName(s); if(user == null) { throw new UsernameNotFoundException("UserName " + s + " not found"); } System.out.println("用户" + s + ":" + user); return user; } }
6.启动类:
@SpringBootApplication public class Start02App { public static void main(String[] args) { SpringApplication.run(Start02App.class, args); } /** * 自定义异常页 */ @Bean public EmbeddedServletContainerCustomizer containerCustomizer() { return new EmbeddedServletContainerCustomizer(){ @Override public void customize(ConfigurableEmbeddedServletContainer container) { container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/error/404")); container.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500")); container.addErrorPages(new ErrorPage(java.lang.Throwable.class,"/error/500")); container.addErrorPages(new ErrorPage(HttpStatus.FORBIDDEN,"/error/403")); } }; } }
7.页面
8.往数据库插入数据(单元测试):
@RunWith(SpringRunner.class) @SpringBootTest(classes = Start02App.class) public class UserServiceTest { @Autowired private UserDao userDao; @Autowired private UserService userService; private ObjectMapper objectMapper = new ObjectMapper(); @Test public void testAll() throws JsonProcessingException { this.saveUser(); this.list(); } private void saveUser() throws JsonProcessingException { User admin = new User(); admin.setUserName("admin"); admin.setPassword(MD5Util.encode("admin")); admin.setPwdBak("admin"); admin.setRole("ADMIN"); User adminSave = userDao.save(admin); for(int i=0;i<=5;i++) { System.out.println("admin save--->:" + objectMapper.writeValueAsString(adminSave)); User user = new User(); user.setUserName("test"+i); user.setPassword(MD5Util.encode("user" + i)); user.setPwdBak("user" + i); user.setRole("USER"); User userSave = userDao.save(user); System.out.println("user save--->:" + objectMapper.writeValueAsString(userSave)); } } private void list() throws JsonProcessingException { List<User> userList = userService.userList(); System.out.println("用户列表:" + objectMapper.writeValueAsString(userList)); } }
查看数据库:
<h4>效果</h4>
启动app类,访问:http://localhost:8080/
测试:
先点击“去主页”或“查看用户列表”,要求输入用户名密码:
使用admin登录,跳转到主页:
返回后,点击去“用户列表”,跳转到403,提示没有权限:
注销后使用普通用户登录,可以跳转到用户列表页面:
测试500页面:
测试404页面:
项目地址:https://github.com/yangzhenlong/mySpringBootDemo/tree/master/springboot11-auth/springboot11-security02FromDB
逃避不一定躲得过,面对不一定最难过