文章目录
SSO单点登录
流程
其实只有一个登录认证的系统,访问其他系统时,会先跳到SSO系统进行认证。
未登陆状态,访问app1系统时的流程:
1、用户访问app1,需要登录
2、跳转到sso系统进行登录
3、用户输入账号密码进行登录
4、将登录状态写入sso的session中,并且在浏览器中写入sso域下的cookie
5、跳转到app1,同时将ticket作为参数传给app1系统
6、app1拿到ticket后,从服务端向sso系统发起请求
7、sso系统验证ticket是否有效,并且获取用户信息
8、sso验证通过之后,app1系统会将用户信息写入session,并设置app1域下的cookie
已登陆app1状态,访问app2系统流程:
1、app2未登录,会跳转到sso系统
2、sso系统已经登陆了(因为sso域下的浏览器有cookie
),直接生成ticket给app2系统
3、跳转到app2,同时将ticket作为参数传给app2系统
4、app2拿到ticket后,从服务端向sso系统发起请求
5、sso系统验证ticket是否有效,并且获取用户信息
6、sso验证通过之后,app2系统会将用户信息写入session,并设置app2域下的cookie
JWT(JSON Web Token)
什么是JWT
JWT能做什么
JWT认证流程
Spring Boot集成 JWT
搭建springboot+mybatis+jwt环境
封装工具类
public class JWTUtils {
private static String TOKEN = "token";
/**
* 生成token
* @param map //传入payload
* @return 返回token
*/
public static String getToken(Map<String,String> map){
JWTCreator.Builder builder = JWT.create();
map.forEach((k,v)->{
builder.withClaim(k,v);
});
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND,7);
builder.withExpiresAt(instance.getTime());
return builder.sign(Algorithm.HMAC256(TOKEN));
}
/**
* 验证token
* @param token
* @return
*/
public static void verify(String token){
JWT.require(Algorithm.HMAC256(TOKEN)).build().verify(token); // 如果验证通过,则不会把报错,否则会报错
}
/**
* 获取token中payload
* @param token
* @return
*/
public static DecodedJWT getToken(String token){
return JWT.require(Algorithm.HMAC256(TOKEN)).build().verify(token);
}
}
引入依赖
主要导入 java-jwt 依赖包
<!--引入jwt-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
<!--引入mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<!--引入lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<!--引入druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.19</version>
</dependency>
<!--引入mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
编写配置
主要是配置数据库连接信息
server.port=8989
spring.application.name=jwt
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/jwt?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=xxx
mybatis.type-aliases-package=com.baizhi.entity
mybatis.mapper-locations=classpath:com/baizhi/mapper/*.xml
logging.level.com.baizhi.dao=debug
自定义拦截器-统计检验token
public class JWTInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取请求头中的token值
String token = request.getHeader("token");
Map<String,Object> map = new HashMap<>();
try {
//检验token,如果正确返回true,否则抛出异常
JWTUtils.verify(token);
return true;
} catch (TokenExpiredException e) {
map.put("state", false);
map.put("msg", "Token已经过期!!!");
} catch (SignatureVerificationException e){
map.put("state", false);
map.put("msg", "签名错误!!!");
} catch (AlgorithmMismatchException e){
map.put("state", false);
map.put("msg", "加密算法不匹配!!!");
} catch (Exception e) {
e.printStackTrace();
map.put("state", false);
map.put("msg", "无效token~~");
}
//封装响应返回
String json = new ObjectMapper().writeValueAsString(map);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(json);
return false;
}
}
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JwtTokenInterceptor()).
excludePathPatterns("/user/**") // 放行
.addPathPatterns("/**"); // 拦截除了"/user/**的所有请求路径
}
}
@RestController
@Slf4j
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/user/login")
public Map<String,Object> login(User user) {
Map<String,Object> result = new HashMap<>();
log.info("用户名: [{}]", user.getName());
log.info("密码: [{}]", user.getPassword());
try {
User userDB = userService.login(user);
Map<String, String> map = new HashMap<>();//用来存放payload
map.put("id",userDB.getId());
map.put("username", userDB.getName());
String token = JWTUtils.getToken(map);
result.put("state",true);
result.put("msg","登录成功!!!");
result.put("token",token); //成功返回token信息
} catch (Exception e) {
e.printStackTrace();
result.put("state","false");
result.put("msg",e.getMessage());
}
return result;
}
}