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

用Spring Boot+Vue做微人事项目第二天
强烈推介IDEA2020.2破解激活,IntelliJ IDEA 注册码,2020.2 IDEA 激活码

用Spring Boot+Vue做微人事项目系列目录

 

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

一、服务端环境搭建

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

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类生成出来,生成的效果如下图所示

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数据就行

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进行测试

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

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

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

访问成功

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

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

@RestController
public class LoginController {

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

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();

    }

}

                                                    觉得文章对自己有用,想要继续学下去的可以

                                                                         可以长按下方二维码        

                                                                

                                                                           关注【javalingfeng】哦

                                                          公众号正在更新vue.js和springboot的详细教程

                                                          还有超多免费Java,Python,Android等系列教程

                                                                                    等你来领

 

 

本文来源凌枫zero,由架构君转载发布,观点不代表Java架构师必看的立场,转载请标明来源出处:https://javajgs.com/archives/8001

发表评论