目录
一、添加登录返回数据结构类
package com.dragonwu.model;
import com.dragonwu.domain.SysMenu;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import java.util.List;
/**
* 登录成功的结果
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value = "登录的结果")
public class LoginResult {
/**
* 登录成功的token,来自我们的authorization-server 里面的
*/
@ApiModelProperty(value = "登录成功的token,来自我们的authorization-server 里面的")
private String token ;
/**
* 该用户的菜单数据
*/
@ApiModelProperty(value = "该用户的菜单数据")
private List<SysMenu> menus ;
/**
* 该用户的权限数据
*/
@ApiModelProperty(value = "该用户的权限数据")
private List<SimpleGrantedAuthority> authorities ;
}
二、添加登录的控制器
package com.dragonwu.controller;
import com.dragonwu.model.LoginResult;
import com.dragonwu.service.SysLoginService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* 登录的控制器
*/
@RestController
@Api(tags = "登录的控制器")
public class SysLoginController {
@Autowired
private SysLoginService loginService;
@PostMapping("/login")
@ApiOperation(value = "后台管理人员登录")
@ApiImplicitParams(
{
@ApiImplicitParam(name = "username", value = "用户名称"),
@ApiImplicitParam(name = "password", value = "用户的密码"),
}
)
public LoginResult login(
@RequestParam(required = true) String username, // 用户名称
@RequestParam(required = true) String password // 用户的密码
) {
return loginService.login(username, password);
}
}
三、添加登录实现的服务
登录服务
package com.dragonwu.service;
import com.dragonwu.model.LoginResult;
/**
* 登录的接口
*/
public interface SysLoginService {
/**
* 登录的实现
* @param username
* 用户名
* @param password
*
* 用户的密码
* @return
* 登录的结果
*/
LoginResult login(String username ,String password) ;
}
实现类
package com.dragonwu.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.enums.ApiErrorCode;
import com.baomidou.mybatisplus.extension.exceptions.ApiException;
import com.dragonwu.domain.SysMenu;
import com.dragonwu.feign.JwtToken;
import com.dragonwu.feign.OAuth2FeignClient;
import com.dragonwu.model.LoginResult;
import com.dragonwu.service.SysLoginService;
import com.dragonwu.service.SysMenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Service
@Slf4j
public class SysLoginServiceImpl implements SysLoginService {
@Autowired
private OAuth2FeignClient oAuth2FeignClient;
@Autowired
private SysMenuService sysMenuService ;
@Value("${basic.token:Basic Y29pbi1hcGk6Y29pbi1zZWNyZXQ=}")
private String basicToken ;
@Autowired
private StringRedisTemplate redisTemplate ;
/**
* 登录的实现
*
* @param username 用户名
* @param password 用户的密码
* @return 登录的结果
*/
@Override
public LoginResult login(String username, String password) {
log.info("用户{}开始登录", username);
// 1 获取token 需要远程调用authorization-server 该服务
ResponseEntity<JwtToken> tokenResponseEntity = oAuth2FeignClient.getToken("password", username, password, "admin_type", basicToken);
if(tokenResponseEntity.getStatusCode()!= HttpStatus.OK){
throw new ApiException(ApiErrorCode.FAILED) ;
}
JwtToken jwtToken = tokenResponseEntity.getBody();
log.info("远程调用授权服务器成功,获取的token为{}", JSON.toJSONString(jwtToken,true));
String token = jwtToken.getAccessToken() ;
// 2 查询我们的菜单数据
Jwt jwt = JwtHelper.decode(token);
String jwtJsonStr = jwt.getClaims();
JSONObject jwtJson = JSON.parseObject(jwtJsonStr);
Long userId = Long.valueOf(jwtJson.getString("user_name")) ;
List<SysMenu> menus = sysMenuService.getMenusByUserId(userId);
// 3 权限数据怎么查询 -- 不需要查询的,因为我们的jwt 里面已经包含了
JSONArray authoritiesJsonArray = jwtJson.getJSONArray("authorities");
List<SimpleGrantedAuthority> authorities = authoritiesJsonArray.stream() // 组装我们的权限数据
.map(authorityJson->new SimpleGrantedAuthority(authorityJson.toString()))
.collect(Collectors.toList());
// 1 将该token 存储在redis 里面,配置我们的网关做jwt验证的操作
redisTemplate.opsForValue().set(token,"", jwtToken.getExpiresIn() ,TimeUnit.SECONDS);
//2 我们返回给前端的Token 数据,少一个bearer:
return new LoginResult(jwtToken.getTokenType()+" "+token, menus, authorities);
}
}
系统菜单服务
package com.dragonwu.service;
import com.dragonwu.domain.SysMenu;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
public interface SysMenuService extends IService<SysMenu>{
/**
* 通过用户的id 查询用户的菜单数据
* @param userId
* @return
*/
List<SysMenu> getMenusByUserId(Long userId);
}
实现类
package com.bjsxt.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dragonwu.domain.SysMenu;
import com.dragonwu.mapper.SysMenuMapper;
import com.dragonwu.service.SysMenuService;
import com.dragonwu.service.SysRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService{
@Autowired
private SysRoleService sysRoleService ;
@Autowired
private SysMenuMapper sysMenuMapper ;
/**
* 通过用户的id 查询用户的菜单数据
*
* @param userId
* @return
*/
@Override
public List<SysMenu> getMenusByUserId(Long userId) {
// 1 如果该用户是超级管理员->>拥有所有的菜单
if(sysRoleService.isSuperAdmin(userId)){
return list() ; // 查询所有
}
// 2 如果该用户不是超级管理员->>查询角色->查询菜单
return sysMenuMapper.selectMenusByUserId(userId);
}
}
角色管理服务
package com.dragonwu.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dragonwu.domain.SysRole;
import com.baomidou.mybatisplus.extension.service.IService;
public interface SysRoleService extends IService<SysRole>{
/**
* 判断一个用户是否为超级的管理员
* @param userId
* @return
*/
boolean isSuperAdmin(Long userId);
/**
* 使用角色的名称模糊分页角色查询
* @param page
* 分页数据
* @param name
* 角色的名称
* @return
*/
Page<SysRole> findByPage(Page<SysRole> page, String name);
}
实现类
package com.dragonwu.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dragonwu.domain.SysRole;
//import com.dragonwu.mapper.SysPrivilegeMapper;
import com.dragonwu.mapper.SysRoleMapper;
import com.dragonwu.service.SysRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
//import java.io.Serializable;
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {
@Autowired
private SysRoleMapper sysRoleMapper;
// @Autowired
// private SysPrivilegeMapper sysPrivilegeMapper ;
//
//
// /**
// * 根据 ID 查询
// *
// * @param id 主键ID
// */
// @Override
// public SysRole getById(Serializable id) {
// SysRole sysRole = super.getById(id);
// sysRole.setPrivileges(sysPrivilegeMapper.selectByRoleId(sysRole.getId()));
// return sysRole;
// }
/**
* 判断一个用户是否为超级的管理员
*
* @param userId
* @return
*/
@Override
public boolean isSuperAdmin(Long userId) {
// 当用户的角色code 为:ROLE_ADMIN 时,该用户为超级的管理员
// 用户的id->用户的角色->该角色的Code是否为ROLE_ADMIN
String roleCode = sysRoleMapper.getUserRoleCode(userId);
if (!StringUtils.isEmpty(roleCode) && roleCode.equals("ROLE_ADMIN")) {
return true;
}
return false;
}
/**
* 使用角色的名称模糊分页角色查询
*
* @param page 分页数据
* @param name 角色的名称
* @return
*/
@Override
public Page<SysRole> findByPage(Page<SysRole> page, String name) {
return page(page, new LambdaQueryWrapper<SysRole>().like(
!StringUtils.isEmpty(name),
SysRole::getName,
name
));
}
}
四、远程调用Feign的类
package com.dragonwu.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(value = "authorization-server")
public interface OAuth2FeignClient {
@PostMapping("/oauth/token")
ResponseEntity<JwtToken> getToken(
@RequestParam("grant_type") String grantType , // 授权类型
@RequestParam("username") String username , // 用户名
@RequestParam("password") String password , // 用户的密码
@RequestParam("login_type") String loginType, // 登录的类型
@RequestHeader("Authorization") String basicToken // Basic Y29pbi1hcGk6Y29pbi1zZWNyZXQ= 由第三方客户端信息加密出现的值
) ;
}
package com.dragonwu.feign;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class JwtToken {
/**
* access_token
*/
@JsonProperty("access_token")
private String accessToken;
/**
* token类型
*/
@JsonProperty("token_type")
private String tokenType;
/**
* refresh_token
*/
@JsonProperty("refresh_token")
private String refreshToken;
/**
* 过期时间
*/
@JsonProperty("expires_in")
private Long expiresIn;
/**
* token的范围
*/
private String scope;
/**
* 颁发的凭证
*/
private String jti;
}
启动类开发Feign调用
@EnableFeignClients
五、Mapper实现
package com.dragonwu.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dragonwu.domain.SysMenu;
import java.util.List;
public interface SysMenuMapper extends BaseMapper<SysMenu> {
/**
* 通过用户的id 查询用户的菜单数据
* @param userId
* @return
*/
List<SysMenu> selectMenusByUserId(Long userId);
/**
* 使用角色的Id 查询所有菜单列表
* @param roleId
* @return
*/
List<SysMenu> selectMenusByRoleId(Long roleId);
}
SysMenuMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dragonwu.mapper.SysMenuMapper">
<resultMap id="BaseResultMap" type="com.dragonwu.domain.SysMenu">
<!--@mbg.generated-->
<!--@Table sys_menu-->
<id column="id" jdbcType="BIGINT" property="id" />
<result column="parent_id" jdbcType="BIGINT" property="parentId" />
<result column="parent_key" jdbcType="VARCHAR" property="parentKey" />
<result column="type" jdbcType="TINYINT" property="type" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="desc" jdbcType="VARCHAR" property="desc" />
<result column="target_url" jdbcType="VARCHAR" property="targetUrl" />
<result column="sort" jdbcType="INTEGER" property="sort" />
<result column="status" jdbcType="TINYINT" property="status" />
<result column="create_by" jdbcType="BIGINT" property="createBy" />
<result column="modify_by" jdbcType="BIGINT" property="modifyBy" />
<result column="created" jdbcType="TIMESTAMP" property="created" />
<result column="last_update_time" jdbcType="TIMESTAMP" property="lastUpdateTime" />
</resultMap>
<sql id="Base_Column_List">
<!--@mbg.generated-->
id, parent_id, parent_key, `type`, `name`, `desc`, target_url, sort, `status`, create_by,
modify_by, created, last_update_time
</sql>
<select id="selectMenusByUserId" resultMap="BaseResultMap">
SELECT
m.id,
m.parent_id,
m.parent_key,
m.`type`,
m.`name`,
m.`desc`,
m.target_url,
m.sort,
m.`status`,
m.create_by,
m.modify_by,
m.created,
m.last_update_time
FROM sys_menu as m
LEFT JOIN sys_role_menu AS rm ON rm.menu_id = m.id
LEFT JOIN sys_user_role AS ur ON ur.role_id = rm.role_id
WHERE
ur.user_id = #{userId}
</select>
<select id="selectMenusByRoleId" resultMap="BaseResultMap">
SELECT
m.id,
m.parent_id,
m.parent_key,
m.`type`,
m.`name`,
m.`desc`,
m.target_url,
m.sort,
m.`status`,
m.create_by,
m.modify_by,
m.created,
m.last_update_time
FROM sys_menu AS m
LEFT JOIN sys_role_menu AS rm ON rm.menu_id = m.id
WHERE
rm.role_id = #{roleId}
ORDER BY m.id
</select>
</mapper>
package com.dragonwu.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dragonwu.domain.SysRole;
public interface SysRoleMapper extends BaseMapper<SysRole> {
/**
* 获取用户角色Code的实现
* @param userId
* @return
*/
String getUserRoleCode(Long userId);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dragonwu.mapper.SysRoleMapper">
<resultMap id="BaseResultMap" type="com.dragonwu.domain.SysRole">
<!--@mbg.generated-->
<!--@Table sys_role-->
<id column="id" jdbcType="BIGINT" property="id"/>
<result column="name" jdbcType="VARCHAR" property="name"/>
<result column="code" jdbcType="VARCHAR" property="code"/>
<result column="description" jdbcType="VARCHAR" property="description"/>
<result column="create_by" jdbcType="BIGINT" property="createBy"/>
<result column="modify_by" jdbcType="BIGINT" property="modifyBy"/>
<result column="status" jdbcType="TINYINT" property="status"/>
<result column="created" jdbcType="TIMESTAMP" property="created"/>
<result column="last_update_time" jdbcType="TIMESTAMP" property="lastUpdateTime"/>
</resultMap>
<sql id="Base_Column_List">
<!--@mbg.generated-->
id, `name`, code, description, create_by, modify_by, `status`, created, last_update_time
</sql>
<select id="getUserRoleCode" resultType="java.lang.String">
SELECT
r.`code`
FROM
sys_role AS r LEFT JOIN sys_user_role as ur on r.id = ur.role_id
WHERE
ur.user_id =#{userId}
</select>
</mapper>
六、测试访问
获取到token切正常,注意关键字。
登录至此实现!