使用springSecurity提供的login接口整合mybatis-plus并使用json格式登录

主要的点

  • springBoot整合mybatis-plus
  • 使用springSecurity做用户权限控制
  • 使用springSecurity提供的login接口整合mybatis-plus并使用json格式登录
  • mybatis-plus使用druid连接池
pom.xml配置
4.0.0jarorg.springframework.boot spring-boot-maven-plugin repackage build-info spring-boot-starter-parent org.springframework.boot 2.5.1 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-starter-actuator com.alibaba druid-spring-boot-starter 1.2.8 mysql mysql-connector-java com.baomidou mybatis-plus-boot-starter 3.4.3 org.projectlombok lombok com.alibaba fastjson 1.2.45 org.zeroturnaround zt-zip 1.13


springboot整合mybatis-plus 导入相关依赖后首先定义实体类
@TableName("user")

@Data
public class User implements UserDetails {
//表名与属性映射 @TableField("name") private String name; //姓名 //表主键 @TableId @TableField("id") private String id; //学号 @TableField("classInt") private int classInt; //班级//通道状态为0时则已提交 @TableField("signs1") private int signs1; //通道1 @TableField("signs2") private int signs2; //通道2 @TableField("signs3") private int signs3; //通道3 @TableField("imgPath") private String imgPath; //图片路径public User(String name, String id, int class_, int signs1, int signs2, int signs3, String imgPath) { this.name = name; this.id = id; classInt = class_; this.signs1 = signs1; this.signs2 = signs2; this.signs3 = signs3; this.imgPath = imgPath; }public User() { }public String getName() { return name; }public void setName(String name) { this.name = name; }public String getId() { return id; }public void setId(String id) { this.id = id; }public int getClassInt() { return classInt; }public void setClassInt(int classInt) { this.classInt = classInt; }public int getSigns1() { return signs1; }public void setSigns1(int signs1) { this.signs1 = signs1; }public int getSigns2() { return signs2; }public void setSigns2(int signs2) { this.signs2 = signs2; }public int getSigns3() { return signs3; }public void setSigns3(int signs3) { this.signs3 = signs3; }public String getImgPath() { return imgPath; }public void setImgPath(String imgPath) { this.imgPath = imgPath; }@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; return classInt == user.classInt && signs1 == user.signs1 && signs2 == user.signs2 && signs3 == user.signs3 && Objects.equals(name, user.name) && Objects.equals(id, user.id) && Objects.equals(imgPath, user.imgPath); }@Override public int hashCode() { return Objects.hash(name, id, classInt, signs1, signs2, signs3, imgPath); }@Override public String toString() { return "Student{" + "name='" + name + '\'' + ", id='" + id + '\'' + ", Class_=" + classInt + ", signs1=" + signs1 + ", signs2=" + signs2 + ", signs3=" + signs3 + ", imgPath='" + imgPath + '\'' + '}'; }}

编写对应的mapper接口
public interface UserMapper extends BaseMapper {}

编写对应的server接口
public interface UserService extends IService {}

编写server实现
@Service public class UserServiceImpl extends ServiceImpl implements UserService, UserDetailsService {}

这时可以通过server接口来直接使用mybatis-plus内置的方法
如果需要添加自己定义的方法
则要在mapper接口中定义这个方法
通过注解或者xml文件编写sql语句,然后在server中定义方法,最后在server实现类中通过@Resource注解来填充mapper变量通过调用mapper来完成自定义的方法
使用springSecurity做用户权限控制
导入相关依赖
springSecurity默认使用表单提交数据,这里想要修改成使用通过fetch使用json格式的数据来通过登录验证
为此需要在登录的用户实体类实现 UserDetails,实现方法
@Override public Collection getAuthorities() { List authorities = new ArrayList<>(); authorities.add(new SimpleGrantedAuthority("ROLE_user")); return authorities; }//这里设置密码为名字 @Override public String getPassword() { return name; }//唯一用户名 @Override public String getUsername() { return id; }@Override public boolean isAccountNonExpired() { return true; }@Override public boolean isAccountNonLocked() { return true; }@Override public boolean isCredentialsNonExpired() { return true; }@Override public boolean isEnabled() { return true; }

自定义CustomAuthenticationFilter类,继承UsernamePasswordAuthenticationFilter
重写方法attemptAuthentication()用来替换掉springSecurity提供的默认方法来实现使用json格式登录
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter { /** * 替换掉SpringSecurity中的attemptAuthentication方法 */ @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {if (request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE) || request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)) { ObjectMapper mapper = new ObjectMapper(); UsernamePasswordAuthenticationToken authRequest = null; try (InputStream is = request.getInputStream()) { Map authenticationBean = mapper.readValue(is, Map.class); authRequest = new UsernamePasswordAuthenticationToken( authenticationBean.get("username"), authenticationBean.get("password")); } catch (IOException e) { e.printStackTrace(); authRequest = new UsernamePasswordAuthenticationToken( "", ""); } finally { setDetails(request, authRequest); return this.getAuthenticationManager().authenticate(authRequest); } } else { return super.attemptAuthentication(request, response); } } }

在登录用户的实体类的serverImpl上实现UserDetailsService
@Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {if (s == null || s.trim().length() == 0) { return null; }User user = userService.getById(s); if (null == user) { return adminServer.loadUserByUsername(s); }else { return user; } }

在Security类上configure()方法
//认证 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userService); }

设置使用json格式
//重新配置登录模块,使用JSON @Bean CustomAuthenticationFilter customAuthenticationFilter() throws Exception { CustomAuthenticationFilter filter = new CustomAuthenticationFilter(); //配置登录成功响应 filter.setAuthenticationSuccessHandler((httpServletRequest, httpServletResponse, authentication) -> { httpServletResponse.setContentType("application/json; charset=utf-8"); httpServletResponse.setStatus(HttpServletResponse.SC_OK); //登录成功后的用户信息 Object principal = authentication.getPrincipal(); PrintWriter out = httpServletResponse.getWriter(); out.write(new ObjectMapper().writeValueAsString(principal)); out.flush(); out.close(); }); filter.setAuthenticationFailureHandler((httpServletRequest, httpServletResponse, e) -> { httpServletResponse.setContentType("application/json; charset=utf-8"); httpServletResponse.setStatus(HttpServletResponse.SC_OK); PrintWriter out = httpServletResponse.getWriter(); JSONObject jsonObject = new JSONObject(); jsonObject.put("status", "登录失败"); out.write(jsonObject.toJSONString()); out.flush(); out.close(); }); //设置身份验证器 filter.setAuthenticationManager(authenticationManagerBean()); return filter; }

下面附上Security配置类上的全部代码
@Configuration @EnableWebSecurity public class Security extends WebSecurityConfigurerAdapter { @Autowired UserServiceImpl userService; //角色继承 @Bean RoleHierarchy roleHierarchy() { RoleHierarchyImpl hierarchy = new RoleHierarchyImpl(); //注意中间有空格 hierarchy.setHierarchy("ROLE_root > ROLE_admin"); return hierarchy; }@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/").permitAll() .antMatchers("/user/**").hasRole("user") .antMatchers("/admin/**").hasRole("admin") .and() .formLogin() .loginProcessingUrl("/login") .and() //关闭csrf保护,会有安全问题,但是在这里不重要 .csrf().disable().exceptionHandling() //没有登录就访问需要登录的接口的回调 .authenticationEntryPoint((request, response, authException) -> { response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setCharacterEncoding("UTF-8"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); PrintWriter out = response.getWriter(); JSONObject jsonObject = new JSONObject(); jsonObject.put("status", "尚未登录,请先登录"); out.write(jsonObject.toJSONString()); out.flush(); out.close(); }) .accessDeniedHandler((request, response, authException)->{ response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setCharacterEncoding("UTF-8"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); PrintWriter out = response.getWriter(); JSONObject jsonObject = new JSONObject(); jsonObject.put("status", "没有权限"); out.write(jsonObject.toJSONString()); out.flush(); out.close(); }) .and() //退出登录状态的回调 .logout() .logoutUrl("/logout") .logoutSuccessHandler((request, response, authentication) -> { response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setCharacterEncoding("UTF-8"); response.setStatus(HttpServletResponse.SC_OK); PrintWriter out = response.getWriter(); JSONObject jsonObject = new JSONObject(); jsonObject.put("status", "注销成功"); out.write(jsonObject.toJSONString()); out.flush(); out.close(); }) .deleteCookies() .permitAll(); http.addFilterAt(customAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); }//认证 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userService); }//密码加密 @Bean PasswordEncoder passwordEncoder() { // BCryptPasswordEncoder:Spring Security 提供的加密工具,可快速实现加密加盐 //现在暂时使用明文存储return NoOpPasswordEncoder.getInstance(); }@Override public void configure(WebSecurity web) throws Exception { //用来配置忽略掉的 URL 地址,一般对于静态文件,我们可以采用此操作 web.ignoring().antMatchers("/js/**", "/css/**"); }//重新配置登录模块,使用JSON @Bean CustomAuthenticationFilter customAuthenticationFilter() throws Exception { CustomAuthenticationFilter filter = new CustomAuthenticationFilter(); //配置登录成功响应 filter.setAuthenticationSuccessHandler((httpServletRequest, httpServletResponse, authentication) -> { httpServletResponse.setContentType("application/json; charset=utf-8"); httpServletResponse.setStatus(HttpServletResponse.SC_OK); //登录成功后的用户信息 Object principal = authentication.getPrincipal(); PrintWriter out = httpServletResponse.getWriter(); out.write(new ObjectMapper().writeValueAsString(principal)); out.flush(); out.close(); }); filter.setAuthenticationFailureHandler((httpServletRequest, httpServletResponse, e) -> { httpServletResponse.setContentType("application/json; charset=utf-8"); httpServletResponse.setStatus(HttpServletResponse.SC_OK); PrintWriter out = httpServletResponse.getWriter(); JSONObject jsonObject = new JSONObject(); jsonObject.put("status", "登录失败"); out.write(jsonObject.toJSONString()); out.flush(); out.close(); }); //设置身份验证器 filter.setAuthenticationManager(authenticationManagerBean()); return filter; }}

mybatis-plus使用druid数据源
druid的配置类
@Configuration public class DruidConfiguration { @Bean public ServletRegistrationBean druidServlet() { //后台服务 ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(); servletRegistrationBean.setServlet(new StatViewServlet()); //访问后台地址 servletRegistrationBean.addUrlMappings("/druid/*"); //后台的登录帐密 Map initParameters = new HashMap<>(); initParameters.put("loginUsername", "tanjunwen"); initParameters.put("loginPassword", "qQ1143042332"); //ip白名单,为空时,代码谁都可以访问 initParameters.put("allow", ""); //ip黑名单 //initParameters.put("deny",""); //设置初始化参数 servletRegistrationBean.setInitParameters(initParameters); return servletRegistrationBean; }//定义数据源 @ConfigurationProperties(prefix = "spring.datasource.druid") @Bean public DataSource druidDataSource() { return new DruidDataSource(); }//配置 Druid 监控 之web 监控的 filter //WebStatFilter:用于配置Web和Druid数据源之间的管理关联监控统计 @Bean public FilterRegistrationBean webStatFilter() { FilterRegistrationBean bean = new FilterRegistrationBean(); bean.setFilter(new WebStatFilter()); //exclusions:设置哪些请求进行过滤排除掉,从而不进行统计 Map initParams = new HashMap<>(); initParams.put("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*,/jdbc/*"); bean.setInitParameters(initParams); //"/*" 表示过滤所有请求 bean.setUrlPatterns(Arrays.asList("/*")); return bean; }}

【使用springSecurity提供的login接口整合mybatis-plus并使用json格式登录】在application.yml文件中添加以下的配置信息
datasource: druid: #连接信息 url: 你的数据库连接地址 username: tanjunwen password: qQ1143042332 driver-class-name: com.mysql.jdbc.Driver #连接池配置 min-idle: 3 initial-size: 3 max-active: 5 #配置获取连接等待超时时间 max-wait: 60000 #间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 time-between-eviction-runs-millis: 120000 #配置一个连接在池中最小的生存时间 min-evictable-idle-time-millis: 300000 #测试连接 validation-query: SELECT 1 from DUAL #申请连接时检测 test-while-idle: true #获取连接时执行检测 test-on-borrow: false #归还连接时检测 test-on-return: false #是否开启PSCache,PSCache对支持游标的数据库性能提升巨大,oracle建议开启,mysql下建议关闭 pool-prepared-statements: false #监控 filter: wall: enabled: true

    推荐阅读