关于java:使用springSecurity提供的login接口整合mybatisplus并使用json格式登录

5次阅读

共计 12917 个字符,预计需要花费 33 分钟才能阅读完成。

次要的点

  • springBoot 整合 mybatis-plus
  • 应用 springSecurity 做用户权限管制
  • 应用 springSecurity 提供的 login 接口整合 mybatis-plus 并应用 json 格局登录
  • mybatis-plus 应用 druid 连接池

pom.xml 配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                        <goal>build-info</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>

</build>

<parent>
    <artifactId>spring-boot-starter-parent</artifactId>
    <groupId>org.springframework.boot</groupId>
    <version>2.5.1</version>
</parent>

<dependencies>
    <!--web-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- 测试 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
    <!-- 平安 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <!-- 监督 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <!--Druid 数据库连接池 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.2.8</version>
    </dependency>
    <!--mysql 驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <!--mybatis_puls-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.3</version>
    </dependency>
    <!--lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    <!-- 阿里解决 JSON 的库 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.45</version>
    </dependency>
    <!--zt-zip-->
    <dependency>
        <groupId>org.zeroturnaround</groupId>
        <artifactId>zt-zip</artifactId>
        <version>1.13</version>
    </dependency>
</dependencies>

</project>

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<User> {

}

编写对应的 server 接口


public interface UserService extends IService<User> {


}

编写 server 实现

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService, UserDetailsService {


}

这时能够通过 server 接口来间接应用 mybatis-plus 内置的办法
如果须要增加本人定义的办法
则要在 mapper 接口中定义这个办法
通过注解或者 xml 文件编写 sql 语句,而后在 server 中定义方法,最初在 server 实现类中通过 @Resource 注解来填充 mapper 变量通过调用 mapper 来实现自定义的办法

应用 springSecurity 做用户权限管制

导入相干依赖
springSecurity 默认应用表单提交数据,这里想要批改成应用通过 fetch 应用 json 格局的数据来通过登录验证
为此须要在登录的用户实体类实现 UserDetails, 实现办法

@Override
    public Collection<? extends GrantedAuthority> getAuthorities() {List<SimpleGrantedAuthority> 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<String, String> 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<String, String> 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<String, String> initParams = new HashMap<>();
        initParams.put("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*,/jdbc/*");
        bean.setInitParameters(initParams);
        //"/*" 示意过滤所有申请
        bean.setUrlPatterns(Arrays.asList("/*"));
        return bean;
    }

}

在 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
正文完
 0