Spring Boot 基于数据库认证
一、设计数据库表
1.库security
2.user表
3.role表
4.user_role表
Bcrypt密码生成计算器 https://www.jisuan.mobi/p163u3BN66Hm6JWx.html
二、添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.9</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
三、数据库配置
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.url=jdbc:mysql:///security spring.datasource.username = root spring.datasource.password = kangxg198811
四、创建实体类
1.Role
public class Role { private Integer id; private String name; private String nameZh; public void setId(Integer id) { this.id = id; } public void setName(String name) { this.name = name; } public void setNameZh(String nameZh) { this.nameZh = nameZh; } public Integer getId() { return id; } public String getName() { return name; } public String getNameZh() { return nameZh; } @Override public String toString() { return "{" + "id=" + id + ", name='" + name + '\'' + ", nameZh='" + nameZh + '\'' + '}'; } }
2.User
@ApiModel(value = "用户实体类",description = "用户信息描述类") public class User implements UserDetails { private Integer id; @ApiModelProperty(value="用户名") private String username; @ApiModelProperty(value="用户密码") private String password; private boolean enabled; private boolean locked; private List<Role> roles; @Override //获取当前用户对象所具有的角色信息 public Collection<? extends GrantedAuthority> getAuthorities() { List<SimpleGrantedAuthority> authorities = new ArrayList<>(); for(Role role : roles) { authorities.add(new SimpleGrantedAuthority((role.getName()))); } return authorities; } @Override//获取当前用户对象的密码 public String getPassword() { return password; } @Override//获取当前用户对象的用户名 public String getUsername() { return username; } public Integer getId() { return id; } public List<Role> getRoles() { return roles; } @Override//当前账户是否过期 public boolean isAccountNonExpired(){ return true; } @Override//当前账户是否锁定 public boolean isAccountNonLocked() { return !locked; } @Override//当前账户密码是否过期 public boolean isCredentialsNonExpired() { return true; } @Override//当前账户是否可用 public boolean isEnabled() { return enabled; } public boolean isLocked() { return locked; } public void setUsername(String username) { this.username = username; } public void setId(Integer id) { this.id = id; } public void setPassword(String password) { this.password = password; } public void setRoles(List<Role> roles) { this.roles = roles; } public void setEnabled(boolean enabled) { this.enabled = enabled; } public void setLocked(boolean locked) { this.locked = locked; } @Override public String toString() { return "{" + "id=" + id + ", name='" + username + '\'' + ", password='" + password + '\'' + ", enabled=" + enabled + ", locked=" + locked + '}'; } }
五、创建UserService
@CrossOrigin @Service public class UserService implements UserDetailsService { @Resource UserMapper userMapper; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userMapper.loadUserByUsername(username); //动过登录输入的用户名去数据库查找用户,如果没有找到就抛出一个异常 if (user == null) { throw new UsernameNotFoundException("账户不存在!"); } //如果查找到了就继续查找该用户所具有到角色信息,并将 获取到到user对象返回,再由系统提供到DaoAuthenticationProvider 类去对比密码是否正确 user.setRoles(userMapper.getUserRolesByUid(user.getId())); return user; } }
六、UserMapper和UserMapper.xml
@Mapper public interface UserMapper { User loadUserByUsername(String username); List<Role> getUserRolesByUid(Integer id); }
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- namespace 表示命名空间 --> <mapper namespace="com.kxg.swagger.mapper.UserMapper"> <select id="loadUserByUsername" resultType="com.kxg.swagger.entity.User"> select * from user where username =#{username} </select> <select id="getUserRolesByUid" resultType="com.kxg.swagger.entity.Role"> select * from role r,user_role ur where r.id =ur.rid and ur.uid=#{id} </select> </mapper>
七、配置Spring Security
@Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired UserService userService;; @Bean 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.authorizeRequests() .antMatchers("/admin/**").hasRole("admin") .antMatchers("/db/**").hasRole("dba") .antMatchers("/user/**").hasRole("user") .anyRequest() .authenticated() .and() .formLogin() .loginPage("/login_page") .loginProcessingUrl("/login") .successHandler(new AuthenticationSuccessHandler() { @Override public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException, JsonProcessingException { Object principal = authentication.getPrincipal(); httpServletResponse.setContentType("application/json;charset=utf-8"); PrintWriter out = httpServletResponse.getWriter(); httpServletResponse.setStatus(200); Map<String,Object> map = new HashMap<>(); map.put("status",200); map.put("msg",principal); ObjectMapper om = new ObjectMapper(); out.write(om.writeValueAsString(map)); out.flush(); out.close(); } }) .failureHandler(new AuthenticationFailureHandler() { @Override public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException, IOException { httpServletResponse.setContentType("application/json;charset=utf-8"); PrintWriter out = httpServletResponse.getWriter(); httpServletResponse.setStatus(200); Map<String,Object> map = new HashMap<>(); map.put("status",401); if (e instanceof LockedException) { map.put("msg","账户被锁定,登录失败!"); } else if(e instanceof BadCredentialsException) { map.put("msg","账户名或密码输入错误,登录失败!"); } else if(e instanceof DisabledException) { map.put("msg","账户被禁用,登录失败!"); } else if(e instanceof AccountExpiredException) { map.put("msg","账户已过期,登录失败!"); } else if(e instanceof CredentialsExpiredException) { map.put("msg","密码已过期,登录失败!"); } else { map.put("msg","登录失败!"); } ObjectMapper om = new ObjectMapper(); out.write(om.writeValueAsString(map)); out.flush(); out.close(); } }) .permitAll() .and() .csrf() .disable(); } }