一.后端登陆接口的实现
1.创建springboot项目导入相关依赖 环境搭建
导入相关依赖进行依赖导入
快速生成数据库逆向工程将生成的文件拷贝进com.liuboss.vhr
因为xml文件放在与mapper放在同一文件夹中要进行相关,要进行pom文件配置
<!--配置mapper映射路径-->
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<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>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<!--配置mapper映射路径-->
<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>
2.在springboot启动类中配置mybatis
@SpringBootApplication
@MapperScan(basePackages = "com.liuboss.vhr.mapper")
public class VhrApplication {
public static void main(String[] args) {
SpringApplication.run(VhrApplication.class, args);
}
}
3.peoperties配置配置文件中进行配置数据源
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql:///vhr?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
项目环境搭建成功
开发登录接口
1.在model模块中Hr接口中继承UserDetails方法
实现其中的方法,
- 用户的权限集, 默认需要添加
ROLE_
前缀 - 用户的加密后的密码, 不加密会使用
{noop}
前缀 - 应用内唯一的用户名
- 账户是否过期
- 账户是否锁定
- 凭证是否过期
- 用户是否可用
注意当有enable实体属性时,要将其中的getenable方法删除。
package com.liuboss.vhr.model;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
/*登陆接口 继承UserDetails 实现其中的方法*/
public class Hr implements UserDetails {
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 == null ? null : name.trim();
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone == null ? null : phone.trim();
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone == null ? null : telephone.trim();
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address == null ? null : address.trim();
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
/*账户是否没有过期*/
return true;
}
/*账户是否没有被锁定*/
@Override
public boolean isAccountNonLocked() {
return true;
}
/*密码是否没有过期*/
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
/*账户是否没有过期*/
return enabled;
}
public void setUsername(String username) {
this.username = username == null ? null : username.trim();
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password == null ? null : password.trim();
}
public String getUserface() {
return userface;
}
public void setUserface(String userface) {
this.userface = userface == null ? null : userface.trim();
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark == null ? null : remark.trim();
}
}
创建service包创建HrSrvice类 并创建其中的的方法 service层创建完成
package com.liuboss.vhr.service;
import com.liuboss.vhr.mapper.HrMapper;
import com.liuboss.vhr.model.Hr;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
/*用户登录模块*/
@Service
public class HrService implements UserDetailsService {
@Autowired
HrMapper hrMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Hr hr = hrMapper.loadUserByUsername(username);
/*判断用户是否为空*/
if(hr == null){
throw new UsernameNotFoundException("用户名不存在");
}
return hr;
}
}
在HrMapper.xml中添加数据库查询方法
<select id="loadUserByUsername" resultMap="BaseResultMap">
select * from hr where username=#{username}
</select>
创建包config 创建类SecurityConfig
继承方法WebSecurityConfigurerAdapter WebSecurityConfigurerAdapter 类是个适配器, 在配置的时候,需要我们自己写个配置类去继承他,然后编写自己所特殊需要的配置
配置其中的密码加密和登陆方法
package com.liuboss.vhr.config;
import com.liuboss.vhr.service.HrService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
HrService hrService;
/*密码加密*/
@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(hrService);
}
}
创建Controller层 连接数据库登陆验证 创建类HelloController
package com.liuboss.vhr.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(){
return "hello";
}
}
启动项目进行测试。
http://localhost:8080/hello 访问页面 会自动跳转到http://localhost:8080/login页面
用户数据数据进行登录验证。 登陆成功后将会进行页面跳转。
登陆成功接入到数据库。
在config的SecurityConfig类中进行实现相应登录方法
package com.liuboss.vhr.config;
import com.liuboss.vhr.service.HrService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
HrService hrService;
/*密码加密*/
@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(hrService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/doLogin")
.loginPage("/login")
.successHandler(new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
}
})
.failureHandler(new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
}
})
.permitAll()
.and()
.logout()
.logoutSuccessHandler(new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
}
})
.permitAll()
.and()
.csrf().disable();
}
}
在model中创建类ResBean
在里面添加三个错误方法的返回页面200 500
package com.liuboss.vhr.model;
import org.apache.catalina.startup.RealmRuleSet;
public class RespBean {
private Integer status;
private String msg;
private Object obj;
//定义错误方法
public static RespBean ok(String msg){
return new RespBean(200,msg,null);
}
public static RespBean ok(String msg,Object obj){
return new RespBean(200,msg,obj);
}
public static RespBean error(String msg){
return new RespBean(500,msg,null);
}
public static RespBean error(String msg,Object obj){
return new RespBean(500,msg,obj);
}
private RespBean() {
}
private RespBean(Integer status, String msg, Object obj) {
this.status = status;
this.msg = msg;
this.obj = obj;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
}
登录页面的验证接口的制作 进行登陆成功和登录失败的及校验和信息的返回
com.liuboss.vhr.config.SecurityConfig
package com.liuboss.vhr.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.liuboss.vhr.model.Hr;
import com.liuboss.vhr.model.RespBean;
import com.liuboss.vhr.service.HrService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.*;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
HrService hrService;
/*密码加密*/
@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(hrService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/doLogin")
.loginPage("/login")
.successHandler(new AuthenticationSuccessHandler() {
/*登陆成功信息*/
@Override
public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
resp.setContentType("application/json;charset=utf-8");
PrintWriter out = resp.getWriter();
Hr hr = (Hr) authentication.getPrincipal();
RespBean ok = RespBean.ok("登陆成功!", 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 {
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("y用户名或密码输入错误,请联系管理员!");
}
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().disable();
}
}
登陆接口完成,测试
用postman进行测试
启动项目
返回 原因 因为没有登陆直接访问 将会报错 告知-要到登陆页进行登录。
进行登录 记住 要输入用户名和密码
登录成功后会返回用户全部信息
登录后在进行访问 用请求进行访问
-------
添加注 注销登录接口和 尚未登录接口提示
尚未登录节接口提示
com.liuboss.vhr.controller.LoginController
package com.liuboss.vhr.controller;
import com.liuboss.vhr.model.RespBean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LoginController {
@GetMapping("/login")
public RespBean login(){
return RespBean.error("您尚未登录!请登录");
}
}
注销登录提示 在权限验证中添加注销登录提示
package com.liuboss.vhr.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.liuboss.vhr.model.Hr;
import com.liuboss.vhr.model.RespBean;
import com.liuboss.vhr.service.HrService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.*;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
HrService hrService;
/*密码加密*/
@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(hrService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/doLogin")
.loginPage("/login")
.successHandler(new AuthenticationSuccessHandler() {
/*登陆成功信息*/
@Override
public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
resp.setContentType("application/json;charset=utf-8");
PrintWriter out = resp.getWriter();
Hr hr = (Hr) authentication.getPrincipal();
RespBean ok = RespBean.ok("登陆成功!", 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 {
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() {
/*注销消息提示
* .logout() 注销登陆
* */
@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().disable();
}
}
Postman测试
http://localhost:8080/doLogin?username=admin&password=123
注销登录
-----------------------
解决前台登录返回登录密码问题
在权限验证中加入
hr.setPassword(null);
加入这句代码前台登录将不会返回密码
后台登录接口阶段性完成。