欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

用Spring Boot+Vue做微人事项目第二天

程序员文章站 2022-05-06 20:37:54
...

前端的登录页面写完了之后呢,开始写后台的登录接口了,后台的登录接口是用Spring Security写的

一、服务端环境搭建

1、创建一个vhr的spring boot项目,并添加spring web、mysql、mybatis和spring srcurity的依赖

用Spring Boot+Vue做微人事项目第二天

2、在pom文件里面添加mysql的版本号和阿里巴巴的druid连接池依赖

 <!--阿里巴巴的druid连接池依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
            <version>5.1.27</version>
        </dependency>

 

3、要用mybatis逆向工具把实体类和mapper类生成出来,生成的效果如下图所示

用Spring Boot+Vue做微人事项目第二天

4、要在启动类上面加上@MapperScan=@MapperScan(basePackages = "com.lqg.vhr.mapper")

@SpringBootApplication
@MapperScan(basePackages = "com.lqg.vhr.mapper")
public class VhrApplication {

    public static void main(String[] args) {
        SpringApplication.run(VhrApplication.class, args);
    }

}

5、再在pom文件的build标签里面配一个resource,因为我的xml文件是写在mapper包下面,打包的时候有可能会过滤掉,所以要配resource,配置代码如下

 <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

6、在application.properties的配置文件里面配置数据库连接属性

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.username=root
spring.datasource.password=123456
#如果需要把数据库部署到linux服务器上,需要加上?useUnicode=true&characterEncoding=UTF-8,确保连接传输的时候的编码也是utf-8
spring.datasource.url=jdbc:mysql://localhost:3306/vur?useUnicode=true&characterEncoding=UTF-8

二、服务端登录接口制作(一)

1、在Hr实体类里面实现UserDetails接口并重写它的方法,用Spring Security自定义登录接口的话就需要让hr类实现UserDetails,如下代码

/**
 * hr
 * @author
 *如果我们需要从数据库里面加载用户,那么我们在定义用户的时候就要实现一个接口UserDetails
 * UserDetails想当于是一个规范,所有人都得实现它,这样的话以后我要获取用户名我就知道就是username,我要获取密码就是password
 */
public class Hr implements UserDetails {
    /**
     * hrID
     */
    private Integer id;

    /**
     * 姓名
     */
    private String name;

    /**
     * 手机号码
     */
    private String phone;

    /**
     * 住宅电话
     */
    private String telephone;

    /**
     * 联系地址
     */
    private String address;

    /**
     * 是否可用
     */
    private Boolean enabled;

    /**
     * 用户名
     */
    private String username;

    /**
     * 密码
     */
    private String password;

    private String userface;

    private String remark;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public void setEnabled(Boolean enabled) {
        this.enabled = enabled;
    }

    @Override
    public String getUsername() {
        return username;
    }


    @Override
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUserface() {
        return userface;
    }

    public void setUserface(String userface) {
        this.userface = userface;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    @Override
    public String toString() {
        return "Hr{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", phone='" + phone + '\'' +
                ", telephone='" + telephone + '\'' +
                ", address='" + address + '\'' +
                ", enabled=" + enabled +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", userface='" + userface + '\'' +
                ", remark='" + remark + '\'' +
                '}';
    }

    /**
     * 账户是否没有过期
     * @return
     */
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    /**
     * 账户是否被锁定
     * @return
     */
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    /**
     * 密码是否没有过期
     * @return
     */
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    /**
     * 是否可用
     * @return
     */
    @Override
    public boolean isEnabled() {
        return enabled;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    /**
     *返回用户的所有角色
     * @return
     */
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }
}

2、创建一个service包,并创建一个HrService类,该类实现了UserDetailsService类,并重写了该类的loadUserByUsername方法,把HrMapper用 

@Autowired

 注解注入进来,详细代码如下:

@Service
public class HrService implements UserDetailsService {

    @Autowired
    HrMapper hrMapper;
    /**
     * 根据用户名加载user对象
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Hr hr = hrMapper.loadUserByUsername(username);
//      判断用户名是否为空,为空则抛出异常
        if (username==null){
            throw new UsernameNotFoundException("用户名不存在!");
        }
        return hr;
    }
}

3、在HrMapper接口中添加loadUserByUsername方法,代码如下

@Repository
public interface HrMapper {
    int deleteByPrimaryKey(Integer id);

    int insert(Hr record);

    int insertSelective(Hr record);

    Hr selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(Hr record);

    int updateByPrimaryKey(Hr record);

     /**
     * 通过用户名查找用户
     * @param username
     * @return
     */
    Hr loadUserByUsername(String username);
}

4、在HrMapper.xml文件中加上如下代码

<!--  根据用户名查询用户-->
  <select id="loadUserByUsername" resultMap="BaseResultMap">
    select * from hr where username=#{username}
  </select>

5、重新创建一个config包,并创建一个SecurityConfig类,该类继承了WebSecurityConfigurerAdapter

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    HrService hrService;

    @Bean
    PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    //要有一个configure方法吧hrService整进来
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(hrService);
    }
}

6、创建一个controller包,并创建一个HelloController类,代码如下:

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello(){
        return "欢迎进入登录页面!";
    }
}

7、登录成功的话,前端是json,前后端分离之后,前端的页面跳转由前端自己去控制,后端只需提供接口,后端只需要返回json数据就行

用Spring Boot+Vue做微人事项目第二天

用Spring Boot+Vue做微人事项目第二天

8、在SecurityConfig里面继续进行配置登录成功或者登录失败向前端传送json数据

①、重写configure方法

@Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
    }

②、通过http.authorizeRequests()进行配置其他请求都是登录之后才能访问的、表单登录、修改默认登录的username、password、处理表单登录的url路径、处理表单登录的url路径、

登录成功的处理、登录失败的处理、跟登录相关的接口就能直接访问、注销成功后的回调、

注销成功后的回调

//配置登录成功或者登录失败向前端传送json数据
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //剩下的其他请求都是登录之后就能访问的
                .anyRequest().authenticated()
                .and()
                //表单登录
                .formLogin()
                //修改默认登录的username
                .usernameParameter("username")
                //修改默认登录的password
                .passwordParameter("password")
                //处理表单登录的url路径
                .loginProcessingUrl("/doLogin")
                //默认看到的登录页面,如果是前后端分离的话,就不用处理表单登录的url路径
                .loginPage("/login")
                //登录成功的处理
                .successHandler(new AuthenticationSuccessHandler() {
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
                        //如果登录成功就返回一段json
                        resp.setContentType("application/json;charset=utf-8");
                        //这是往出写的
                        PrintWriter out = resp.getWriter();
                        //登录成功的hr对象
                        Hr hr = (Hr)authentication.getPrincipal();
                        RespBean ok = RespBean.ok("登录成功!", hr);
                        //把hr写成字符串
                        String s = new ObjectMapper().writeValueAsString(ok);
                        //把字符串写出去
                        out.write(s);
                        out.flush();
                        out.close();


                    }
                })
                //登录失败的处理
                .failureHandler(new AuthenticationFailureHandler() {
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException exception) throws IOException, ServletException {
                        //如果登录成功就返回一段json
                        resp.setContentType("application/json;charset=utf-8");
                        //这是往出写的
                        PrintWriter out = resp.getWriter();
                        RespBean respBean = RespBean.error("登录失败!");
                        if(exception instanceof LockedException){
                            respBean.setMsg("账户被锁定,请联系管理员!");
                        }else if (exception instanceof CredentialsExpiredException){
                            respBean.setMsg("密码过期,请联系管理员!");
                        }else if (exception instanceof AccountExpiredException){
                            respBean.setMsg("账户过期,请联系管理员!");
                        }else if (exception instanceof DisabledException){
                            respBean.setMsg("账户被禁用,请联系管理员!");
                        }else if (exception instanceof BadCredentialsException){
                            respBean.setMsg("用户名或者密码输入错误,清联系管理员!");
                        }
                        out.write(new ObjectMapper().writeValueAsString(respBean));
                        out.flush();
                        out.close();
                    }
                })
                //跟登录相关的接口就能直接访问
                .permitAll()
                .and()
                .logout()
                //注销成功后的回调
                .logoutSuccessHandler(new LogoutSuccessHandler() {
                    @Override
                    public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {

                    }
                })
                .permitAll()
                .and()
                //关闭csrf攻击
                .csrf().disable();

    }

9、通过postman进行测试

用Spring Boot+Vue做微人事项目第二天

访问hello接口,出现404,本来应该出来401的,但是访问hello接口的时候,它发现你没有登录,所以要你去登录页,SecurityConfig类里面没有配置登录页,所以就报404

我再去访问doLogin,访问结果图片如下:

用Spring Boot+Vue做微人事项目第二天

登录成功,再在postman里面测试hello接口

用Spring Boot+Vue做微人事项目第二天

访问成功

三、服务端登录接口制作(一)

1、因为访问hello接口返回的是404,所以要把页面改成返回成json格式的数据,重新创建一个LoginController,代码如下:

@RestController
public class LoginController {

    @GetMapping("/login")
    public RespBean login(){
        return RespBean.error("尚未登录,请登录!")
    }
}

用Spring Boot+Vue做微人事项目第二天

2、再把SecurityConfig配置类的注销成功后的回调完善一下,首先设置返回类型为json类型,然后使用resp.getWrite()方法进行输出,代码如下

//注销成功后的回调
                .logoutSuccessHandler(new LogoutSuccessHandler() {
                    @Override
                    public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
                        resp.setContentType("application/json;charset=utf-8");
                        PrintWriter out = resp.getWriter();
                        out.write(new ObjectMapper().writeValueAsString(RespBean.ok("注销成功!")));
                        out.flush();
                        out.close();
                    }
                })

SecurityConfig配置类的详细代码如下:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    HrService hrService;

    @Bean
    PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    //要有一个configure方法吧hrService整进来
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(hrService);
    }

    //配置登录成功或者登录失败向前端传送json数据
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //剩下的其他请求都是登录之后就能访问的
                .anyRequest().authenticated()
                .and()
                //表单登录
                .formLogin()
                //修改默认登录的username
                .usernameParameter("username")
                //修改默认登录的password
                .passwordParameter("password")
                //处理表单登录的url路径
                .loginProcessingUrl("/doLogin")
                //默认看到的登录页面,如果是前后端分离的话,就不用配置登录页面
                .loginPage("/login")
                //登录成功的处理
                .successHandler(new AuthenticationSuccessHandler() {
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
                        //如果登录成功就返回一段json
                        resp.setContentType("application/json;charset=utf-8");
                        //这是往出写的
                        PrintWriter out = resp.getWriter();
                        //登录成功的hr对象
                        Hr hr = (Hr)authentication.getPrincipal();
                        hr.setPassword(null);
                        RespBean ok = RespBean.ok("登录成功!", hr);
                        //把hr写成字符串
                        String s = new ObjectMapper().writeValueAsString(ok);
                        //把字符串写出去
                        out.write(s);
                        out.flush();
                        out.close();


                    }
                })
                //登录失败的处理
                .failureHandler(new AuthenticationFailureHandler() {
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException exception) throws IOException, ServletException {
                        //如果登录成功就返回一段json
                        resp.setContentType("application/json;charset=utf-8");
                        //这是往出写的
                        PrintWriter out = resp.getWriter();
                        RespBean respBean = RespBean.error("登录失败!");
                        if(exception instanceof LockedException){
                            respBean.setMsg("账户被锁定,请联系管理员!");
                        }else if (exception instanceof CredentialsExpiredException){
                            respBean.setMsg("密码过期,请联系管理员!");
                        }else if (exception instanceof AccountExpiredException){
                            respBean.setMsg("账户过期,请联系管理员!");
                        }else if (exception instanceof DisabledException){
                            respBean.setMsg("账户被禁用,请联系管理员!");
                        }else if (exception instanceof BadCredentialsException){
                            respBean.setMsg("用户名或者密码输入错误,请重新输入!");
                        }
                        out.write(new ObjectMapper().writeValueAsString(respBean));
                        out.flush();
                        out.close();
                    }
                })
                //跟登录相关的接口就能直接访问
                .permitAll()
                .and()
                .logout()
                //注销成功后的回调
                .logoutSuccessHandler(new LogoutSuccessHandler() {
                    @Override
                    public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
                        resp.setContentType("application/json;charset=utf-8");
                        PrintWriter out = resp.getWriter();
                        out.write(new ObjectMapper().writeValueAsString(RespBean.ok("注销成功!")));
                        out.flush();
                        out.close();
                    }
                })
                .permitAll()
                .and()
                //关闭csrf攻击
                .csrf().disable();

    }

}