SpringBoot整合SSO(singlesignon)单点登录1、单点登录三种常见的⽅式
(1)Session⼴播机制(Session复制)
(2)使⽤Cookie+Redis实现
(3)使⽤token实现
2、单点登录介绍
举例:
(1)引⼊jwt依赖
<!-- JWT-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
(2)创建JWTUtils⼯具类
public class JwtUtils {
//token过期时间
public static final long EXPIRE = 1000 * 60 * 60 * 24;
//秘钥
public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO"; public static String getJwtToken(String id, String nickname){
String JwtToken = Jwts.builder()
//设置头信息
.setHeaderParam("typ", "JWT")
.setHeaderParam("alg", "HS256")
.setSubject("user")
.setIssuedAt(new Date())
//设置过期时间
.setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
//设置token主体部分(这⾥使⽤id和nickname作为主体部分)
.claim("id", id)
.claim("nickname", nickname)
//加密⽅式
.signWith(SignatureAlgorithm.HS256, APP_SECRET)
pact();
return JwtToken;
}
/**
* 判断token是否存在与有效(直接通过APP_SECRET解析token)
* @param jwtToken
* @return
*/
public static boolean checkToken(String jwtToken) {
if(StringUtils.isEmpty(jwtToken)) return false;
try {
Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 判断token是否存在与有效(通过获取请求头信息获取token再使⽤APP_SECRET解析token)
* @param request
* @return
*/
public static boolean checkToken(HttpServletRequest request) {
try {
String jwtToken = Header("token");
if(StringUtils.isEmpty(jwtToken)) return false;
Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 根据token字符串获取⽤户id(取出有效载荷中的⽤户信息)
* @param request
* @return
*/
public static String getMemberIdByJwtToken(HttpServletRequest request) {
String jwtToken = Header("token");
if(StringUtils.isEmpty(jwtToken)) return "";
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken); Claims claims = Body();
return (("id");
}
}
3、单点登录实现
项⽬⽬录结构
UcenterMemberController
@RestController
@RequestMapping("/user/")
@CrossOrigin
public class UcenterMemberController {
@Autowired
private UcenterMemberService ucenterMemberService;
//登录
@PostMapping("login")
public ResponseResult login(@RequestBody MobileLoginRequest request) {
String token = ucenterMemberService.login(request);
return ResponseResult.success().data("token", token);
}
//注册
@PostMapping("register")
public ResponseResult register(@RequestBody RegisterRequest request) {
return ResponseResult.success().message("注册成功");
}
//根据token获取⽤户信息
@GetMapping("getUserInfo")
public ResponseResult getUserInfo(HttpServletRequest request) {
/
/调⽤jwt⼯具类的⽅法,根据request对象获取头信息,返回⽤户id
String id = MemberIdByJwtToken(request);
//根据⽤户id查询⽤户
UcenterMember member = ById(id);
return ResponseResult.success().data("userInfo", member);
}
}
ServiceImpl
@Service
public class UcenterMemberServiceImpl extends ServiceImpl<UcenterMemberMapper, UcenterMember> implements UcenterMemberService {
@Autowired
private StringRedisTemplate redisTemplate;
//登录
@Override
public String login(MobileLoginRequest request) {
String phone = Phone();
String password = Password();
if (StrUtil.isBlank(phone) || StrUtil.isBlank(password)) {
throw new GuliException(200001, "请输⼊⽤户名或者密码");
}
//根据输⼊的⼿机号码查该⽤户信息
UcenterMember ucenterByPhone = this.baseMapper.selectOne(new LambdaQueryWrapper<Ucenter
Member>().eq(UcenterMember::getMobile, phone)); if (ucenterByPhone == null) {
throw new GuliException(200002, "该⽤户名不存在");
}
//如果⽤户存在⽐对数据库密码和⽤户输⼊的密码
if (!pt(password).Password())) {
throw new GuliException(200003, "密码输⼊错误");
}
String token = Id(), Nickname());
return token;
}
//注册
@Override
public void register(RegisterRequest request) {
String phone = Phone();
String password = Password();
String nickName = NickName();
String code = Code();
if (StrUtil.isBlank(phone) || StrUtil.isBlank(password) || StrUtil.isBlank(nickName) || StrUtil.isBlank(code)) {
throw new GuliException(200001, "请填写相关信息");
}
//判断⼿机号是否重复
Integer count = baseMapper.selectCount(new LambdaQueryWrapper<UcenterMember>().eq(UcenterMember::getMobile, phone));
if (count > 0) {
throw new GuliException(200001, "账号已经存在请重新输⼊");
}
//验证code
String redisCode = redisTemplate.opsForValue().get(phone);
if (StrUtil.isBlank(redisCode)) {
throw new GuliException(200001, "验证码已经过期,请重新获取");
}
if (!redisCode.equals(code)) {
throw new GuliException(200001, "验证码错误");
}
UcenterMember ucenterByPhone = new UcenterMember();
ucenterByPhone.setMobile(phone);
ucenterByPhone.pt(password));
ucenterByPhone.setNickname(nickName);
ucenterByPhone.setIsDisabled(false);
int insert = baseMapper.insert(ucenterByPhone);
if(insert<=0){
throw new GuliException(20001,"注册失败");
}
}
}
MD5加密算法⼯具类
public final class MD5Util {
public static String encrypt(String strSrc) {
try {
char hexChars[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'a', 'b', 'c', 'd', 'e', 'f'};
byte[] bytes = Bytes();
MessageDigest md = Instance("MD5");
md.update(bytes);
bytes = md.digest();
int j = bytes.length;
char[] chars = new char[j * 2];
int k = 0;
for (int i = 0; i < bytes.length; i++) {
byte b = bytes[i];
chars[k++] = hexChars[b >>> 4 & 0xf];
chars[k++] = hexChars[b & 0xf];
}
return new String(chars);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
throw new RuntimeException("MD5加密出错!!+" + e);
}
}
public static void main(String[] args) {
System.out.pt("111111"));
}
}
4、登录完成后在前端界⾯展⽰⽤户信息
(1)第⼀、⼆、四步:登录的⽅法(记得npm install js-cookie)
//登录的⽅法
submitLogin() {
//第⼀步调⽤接⼝进⾏登录,返回token字符串
loginApi.submitLoginUser(this.user)
.then(response => {
//第⼆步获取token字符串放到cookie⾥⾯
//第⼀个参数cookie名称,第⼆个参数值,第三个参数作⽤范围
cookie.set('user_token',response.ken,{domain: 'localhost'})
//第四步调⽤接⼝根据token获取⽤户信息,为了⾸页⾯显⽰
.
then(response => {
this.loginInfo = response.data.data.userInfo
//获取返回⽤户信息,放到cookie⾥⾯(主页在cookie中获取⽤户信息进⾏展⽰)
cookie.set('user_info',this.loginInfo,{domain: 'localhost'})
//跳转页⾯
window.location.href = "/";
})
})
},
(2)第三步:在request.js中编写前端请求(发送请求携带token)
// 创建axios实例
const service = ate({
baseURL: v.BASE_API, // api 的 base_url
timeout: 5000 // 请求超时时间
})
// request
quest.use(
config => {
if (('user_token')) {
config.headers['token'] = ('user_token') // 让每个请求携带⾃定义token 请根据实际情况⾃⾏修改 }
return config
},
error => {
// Do something with request error
console.log(error) // for debug
}
)
(3)第五步:主页显⽰⽤户信息(从cookie中获取⽤户信息)
//创建⽅法,从cookie获取⽤户信息
showInfo() {
//从cookie获取⽤户信息
var userStr = ('guli_ucenter')
/
/ 把字符串转换json对象(js对象),因为后端传过来的是"{'name','lucy','age':18}"的格式
if(userStr) {
this.loginInfo = JSON.parse(userStr)
}
}
显⽰⽤户信息(根据userInfo中id来判断)
<ul class="h-r-login">
//cookie中没有⽤户信息,显⽰登录和注册
<li v-if="!loginInfo.id" id="no-login">
<a href="/login" rel="external nofollow" title="登录">
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论