导入依赖,下面的依赖是在这次OA登录中用到的
<!--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>
<scope>test</scope>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--Swagger2-->
<!--Swagger-UI-->
<!--访问路径:http://localhost:8080/swagger-ui.html-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!--swaggerui 几个自定义界面方便查看接口-->
<!--访问路径:http://localhost:8080/doc.html-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>25.1-jre</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--JWT依赖-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
<!-- 热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!--google kaptcha验证码依赖-->
<dependency>
<groupId>com.github.axet</groupId>
<artifactId>kaptcha</artifactId>
<version>0.0.9</version>
</dependency>
<!--spring data redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
编写配置文件
server:
port: 8081
spring:
mvc:
pathmatch:
# \u89E3\u51B3spring2.6\u4EE5\u540E\u6574\u4E2Aswagger2\u7684\u95EE\u9898
matching-strategy: ant_path_matcher
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/yeb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: root
hikari:
# \u8FDE\u63A5\u6C60\u540D
pool-name: DataHikariCP
# \u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5\u6570
minimum-idle: 5
# \u7A7A\u95F2\u8FDE\u63A5\u5B58\u6D3B\u6700\u5927\u65F6\u95F4\uFF0C\u9ED8\u8BA460000\uFF0810\u5206\u949F\uFF09
idle-timeout: 180000
# \u6700\u5927\u8FDE\u63A5\u6570\uFF0C\u9ED8\u8BA410
maximum-pool-size: 10
# \u4ECE\u8FDE\u63A5\u6C60\u8FD4\u56DE\u7684\u8FDE\u63A5\u7684\u81EA\u52A8\u63D0\u4EA4
auto-commit: true
# \u8FDE\u63A5\u6700\u5927\u5B58\u6D3B\u65F6\u95F4\uFF0C0\u8868\u793A\u6C38\u4E45\u5B58\u6D3B\uFF0C\u9ED8\u8BA41800000\uFF0830\u5206\u949F\uFF09
max-lifetime: 1800000
# \u8FDE\u63A5\u8D85\u65F6\u65F6\u95F4\uFF0C\u9ED8\u8BA430000\uFF0830\u79D2\uFF09
connection-timeout: 30000
# \u6D4B\u8BD5\u8FDE\u63A5\u662F\u5426\u53EF\u7528\u7684\u67E5\u8BE2\u8BED\u53E5
connection-init-sql: SELECT 1
redis:
# \u8D85\u65F6\u65F6\u95F4
timeout: 10000ms
# \u670D\u52A1\u5668\u5730\u5740
host: 127.0.0.1
# \u670D\u52A1\u5668\u7AEF\u53E3
port: 6379
database: 0
lettuce:
pool:
# \u8FDE\u63A5\u6C60\u6700\u5927\u8FDE\u63A5\u6570 \u9ED8\u8BA48 \uFF0C\u8D1F\u6570\u8868\u793A\u6CA1\u6709\u9650\u5236
max-active: 1024
# \u6700\u5927\u8FDE\u63A5\u963B\u585E\u7B49\u5F85\u65F6\u95F4\uFF0C\u9ED8\u8BA4-1
max-wait: 10000ms
# \u6700\u5927\u7A7A\u95F2\u8FDE\u63A5
max-idle: 200
# \u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5
min-idle: 5
password:
mybatis-plus:
mapper-locations: classpath*:mapper/**/*Mapper.xml
type-aliases-package: com.atguigu.oaserver.pojo
configuration:
# \u5173\u95ED\u81EA\u52A8\u9A7C\u5CF0\u547D\u540D
map-underscore-to-camel-case: false
# mybatis SQL \u6253\u5370
logging:
level:
com.atguigu.oaserver.mapper: debug
jwt:
# JWT存储的请求头
tokenHeader: Authorization
# JWT加密使用的密钥
secret: yeb-secret
# JWT的超期限时间(60*60*24) 即24小时失效
expiration: 604800000
# JWT载荷中拿到开头 不要改
tokenHead: Bearer
之后再用代码生成器生成所需要的类,接口
在controller定义登录方法
加载用户信息,判断密码,账号转态
因为要判断加密密码所以要用到passwordEncoder
loadUserByUsername通过实现userDetailsService来的
在TAdminUserDetailsServiceImpl里面判断用户是否存在
getAdminByUserName就是一个单查,根据username去查询用户是否存在
@Override public TAdmin getAdminByUserName(String username) { QueryWrapper<TAdmin> qw = new QueryWrapper(); qw.eq("username", username); TAdmin one = this.getOne(qw); return one; }
账号状态和密码都没有问题之后生成token
RespBean工具类,用来响应结果封装类,用于统一返回给前端的数据格式
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RespBean {
// 响应状态码
private long code;
// 响应消息
private String msg;
// 响应数据
private Object data;
/**
* 创建一个成功的响应结果,不包含数据
*
* @param message 响应消息
* @return 成功的响应结果
*/
public static RespBean success(String message) {
return new RespBean(200, message, null);
}
/**
* 创建一个成功的响应结果,包含数据
*
* @param message 响应消息
* @param obj 响应数据
* @return 成功的响应结果
*/
public static RespBean success(String message, Object obj) {
return new RespBean(200, message, obj);
}
/**
* 创建一个失败的响应结果,不包含数据
*
* @param message 响应消息
* @return 失败的响应结果
*/
public static RespBean error(String message) {
return new RespBean(500, message, null);
}
/**
* 创建一个失败的响应结果,包含数据
*
* @param message 响应消息
* @param obj 响应数据
* @return 失败的响应结果
*/
public static RespBean error(String message, Object obj) {
return new RespBean(500, message, obj);
}
}
JwtUtils工具类
@Data
@Component
public class JwtUtils {
@Value("${jwt.tokenHead}")
String tokenHead;
@Value("${jwt.secret}")
String secret;
@Value("${jwt.expiration}")
int expiration;
@Value("${jwt.tokenHeader}")
private String tokenHeader;
public String genenerateToken(String username) {
Date exDate = new Date(System.currentTimeMillis() + expiration);
return Jwts.builder()
.setSubject(username)// 主题
.setIssuedAt(new Date())// 签发时间
.setExpiration(exDate)// 过期时间
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
}
上面的@value来之配置文件yml,tokenHeader的值一定不要更改
jwt:
# JWT存储的请求头
tokenHeader: Authorization
# JWT加密使用的密钥
secret: yeb-secret
# JWT的超期限时间(60*60*24) 即24小时失效
expiration: 604800000
# JWT载荷中拿到开头 不要改
tokenHead: Bearer
这边既然需要登录那必然要编写security用来登录
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// 允许访问/login
http.authorizeRequests()
.mvcMatchers("/login").permitAll()
.anyRequest().permitAll();
// 关闭csrf
http.csrf().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// 禁用缓存
http.headers()
.cacheControl();
}
之后根据自己配置的端口号和数据库中的数据进行登录测试
比如我的就是:localhost:8081/login?username=admin&password=123456
如果浏览器装配了JSON插件,然后不出意外的话就可以在浏览器看到这样子的
后面就是获取token里面的数据,你登录之后把登录的用户的数据存入token,那如何获取它呢
先来编写一个这样子方法
/**
* 获取管理员信息
*
* @param token 用户名和密码认证令牌,用于获取当前登录的管理员信息
* @return RespBean 包含管理员信息的响应对象
*/
@RequestMapping("/admin/info")
public RespBean getAminInfo(UsernamePasswordAuthenticationToken token) {
// 从认证令牌中获取管理员对象
TAdmin principal = (TAdmin) token.getPrincipal();
// 打印管理员信息,用于调试和日志记录
System.out.println(principal);
// 返回成功响应,包含管理员信息
return RespBean.success("获取用户信息成功", principal);
}
你想要获取登录人员的信息,那就要有个JWT认证过滤器
/**
* JWT认证过滤器,用于拦截请求并验证JWT令牌
*/
public class JwtAuthencationTokenFilter extends OncePerRequestFilter {
@Autowired
private JwtUtils jwtUtils;
@Autowired
private TAdminUserDetailsServiceImpl userDetailsService;
/**
* 执行过滤器的主要方法
*
* @param request HttpServletRequest对象,用于获取请求信息
* @param response HttpServletResponse对象,用于设置响应信息
* @param filterChain 过滤链,用于将请求传递给下一个过滤器或目标资源
* @throws ServletException 如果过滤过程中发生Servlet异常
* @throws IOException 如果过滤过程中发生IO异常
*/
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 从请求头中获取JWT令牌
String token = request.getHeader(jwtUtils.getTokenHeader());
// 打印令牌信息,用于调试
System.out.println("token=======>" + token);
if (token != null && token.startsWith(jwtUtils.getTokenHead())) {
// 移除令牌前缀,获取纯令牌字符串
String[] s = token.split(" ");
token = s[1];
System.out.println("token=======>" + token);
// 从令牌中提取用户名
String username = jwtUtils.getUserNameFromTokens(token);
System.out.println("username=======>" + username);
// 如果用户名不为空且上下文中尚未进行认证
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
// 根据用户名获取用户详细信息
TAdmin tAdmin = (TAdmin) userDetailsService.loadUserByUsername(username);
// 设置认证信息
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(tAdmin, null, tAdmin.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
}
// 将请求传递给过滤链中的下一个元素
filterChain.doFilter(request, response);
}
}
然后这个过滤器放到security里面进行添加
之后就可以用ApiFox这个软件来进行测试
先打开apifox,就是下面图中的软件
然后跟着下面的步骤来
这里的信息来着登录成功之后的tokenHead和token,tokenHead后面记得打空格
这样就可以看到登录的用户信息了