说明:今天有个哥们问我有没有什么好的权限框架推荐,我了解了一下他们对业务的要求,我反手就给他推荐了Security权限框架,他说他看过我之前的Shiro权限管理博客,感觉Shiro不错。我说区别不大,Security除了不能脱离Spring,Shiro能做的Security都能做,而且Security对oauth、OpenID等也有支持,Shiro就需要自己手动去实现了。那哥们就说:关键你没有写过Security相关的博客啊!当时我脑瓜子就嗡嗡的,这是那儿跟那儿啊。。。。。。后来感觉Security也用过几次了,整理成博客也可以吧。
细节可以查看官网,这里只是使用!
工程目录:
1.pom.xml文件
4.0.0 org.springframework.boot spring-boot-starter-parent2.1.6.RELEASE Security_Pub Security_Pub1.0-SNAPSHOT war Security_Pub Maven Webapp http://www.example.com UTF-8 1.8 1.8 4.12 1.2.17 1.14.8 1.1.16 2.6 2.1.3.RELEASE 2.7.0 3.0.1 1.2.10 5.1.39 org.springframework.boot spring-boot-starter-weborg.springframework.security spring-security-taglibsorg.springframework.boot spring-boot-starter-securityorg.thymeleaf.extras thymeleaf-extras-springsecurity5org.projectlombok lombok${lombok.version} io.springfox springfox-swagger2${springfox.version} io.springfox springfox-swagger-ui${springfox.version} com.github.pagehelper pagehelper-spring-boot-starter${pagehelper.spring.boot.starter.version} com.baomidou mybatis-plus-boot-starter${mybatis.plus.boot.starter.version} mysql mysql-connector-java${mysql-connector.version} org.springframework.boot spring-boot-starter-data-redis${redis.version} com.alibaba fastjson1.2.70 compile apache-lang commons-lang2.0
2.application.yml文件
server:
port: 8080
#数据源
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/my_security_test?useUnicode=true&characterEncoding=UTF-8
username: root
password: root
#日期配置 yyyy-MM-dd HH:mm:ss
jackson:
date-format: yyyy-MM-dd HH:mm:ss
#映射xml
mybatis-plus:
mapper-locations: classpath:mapping
@Data
public class Result {
@ApiModelProperty(value = "返回码")
private int code;
@ApiModelProperty(value = "返回数据")
private Object data;
@ApiModelProperty(value = "返回描述")
private String msg;
@ApiModelProperty(value = "返回长度")
private long count;
public static Result success(List
4.MyException.java
package com.dev.config.exception;
public class MyException extends RuntimeException{
private int code;
private String msg;
public MyException(int code, String msg){
super(msg);
this.code = code;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
5.TopException.java
package com.dev.config.exception;
import com.dev.common.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@ControllerAdvice
public class TopException {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Result handle(Exception e){
if(e instanceof MyException){
logger.error("业务日志",e);
MyException myException = (MyException) e;
return Result.error(myException.getCode(),myException.getMessage());
}else if(e instanceof AccessDeniedException){
return Result.error(403,"访问权限不足");
}
logger.error("系统日志",e);
return Result.error(1000,"业务繁忙");
}
}
6.UserAccessDeniedHandler.java
package com.dev.config.security.handler;
import com.dev.common.Result;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class UserAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
Result.responseJson(response, Result.response(403, "权限不足,拒绝访问", accessDeniedException.getMessage()));
}
}
7.UserAuthenticationProvider.java
package com.dev.config.security.handler;
import com.dev.config.security.Md5Util;
import com.dev.model.SysUserDetails;
import com.dev.service.impl.SysUserDetailsService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
@Component
public class UserAuthenticationProvider implements AuthenticationProvider {
@Autowired
private SysUserDetailsService userDetailsService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = (String) authentication.getPrincipal(); // 获取用户名
String password = (String) authentication.getCredentials(); // 获取密码
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
throw new UsernameNotFoundException("用户名或密码不能为空");
}
if(username.equals("admin") && password.equals("123456")){
SysUserDetails sysUserDetails = (SysUserDetails) userDetailsService.loadUserByUsername(username);
return new UsernamePasswordAuthenticationToken(sysUserDetails, password, sysUserDetails.getAuthorities());
} else if (username.equals("admin") && !password.equals("123456")){
throw new BadCredentialsException("用户名或密码错误");
} else {
SysUserDetails sysUserDetails = (SysUserDetails) userDetailsService.loadUserByUsername(username);
if (sysUserDetails == null) {
throw new UsernameNotFoundException("用户名不存在");
}
if(!sysUserDetails.getPassword().equals(Md5Util.MD5(password))){
throw new BadCredentialsException("用户名或密码错误");
}
return new UsernamePasswordAuthenticationToken(sysUserDetails, password, sysUserDetails.getAuthorities());
}
}
@Override
public boolean supports(Class> authentication) {
return true;
}
}
8.UserLoginFailureHandler.java
package com.dev.config.security.handler;
import com.dev.common.Result;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class UserLoginFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) {
Result.responseJson(response, Result.response(500, "登录失败", exception.getMessage()));
}
}
9.UserLoginSuccessHandler.java
package com.dev.config.security.handler;
import com.dev.common.Result;
import com.dev.model.SysUserDetails;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
@Component
public class UserLoginSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) {
SysUserDetails sysUserDetails = (SysUserDetails) authentication.getPrincipal();
Map tokenMap = new HashMap<>();
HttpSession session = request.getSession();
session.setAttribute("user", sysUserDetails);
Result.responseJson(response, Result.response(0, "登录成功", tokenMap));
}
}
10.UserLogoutSuccessHandler.java
package com.dev.config.security.handler;
import com.dev.common.Result;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class UserLogoutSuccessHandler implements LogoutSuccessHandler {
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) {
SecurityContextHolder.clearContext();
Result.responseJson(response, Result.response(200, "登出成功", null));
}
}
11.UserNotLoginHandler.java
package com.dev.config.security.handler;
import com.dev.common.Result;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class UserNotLoginHandler implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
Result.responseJson(response, Result.response(401, "未登录", authException.getMessage()));
}
}
12.UserPermissionevaluator.java
package com.dev.config.security.handler;
import com.dev.config.exception.MyException;
import com.dev.model.SysUserDetails;
import com.dev.model.TSysRes;
import com.dev.service.TSysResService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.Permissionevaluator;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Configuration
@Component
public class UserPermissionevaluator implements Permissionevaluator {
@Autowired
private TSysResService tSysResService;
@Override
public boolean hasPermission(Authentication authentication, Object targetUrl, Object permission) {
SysUserDetails sysUserDetails = null;
try {
sysUserDetails = (SysUserDetails) authentication.getPrincipal();
} catch (Exception e){
throw new MyException(403,"权限不足");
}
Set permissions = new HashSet(); // 用户权限
List authList = tSysResService.findResByUserId(sysUserDetails.getId());
for (int i = 0; i < authList.size() ; i++) {
permissions.add(authList.get(i).getPermission());
}
// 判断是否拥有权限
if (permissions.contains(permission.toString())) {
return true;
}
return false;
}
@Override
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType,
Object permission) {
return false;
}
}
13.AutoSecurityConfig.java
package com.dev.config.security;
import com.dev.config.security.handler.*;
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.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.expression.DefaultWebSecurityexpressionHandler;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法权限注解
public class AutoSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserAccessDeniedHandler userAccessDeniedHandler;
@Autowired
private UserNotLoginHandler userNotLoginHandler;
@Autowired
private UserLoginSuccessHandler userLoginSuccessHandler;
@Autowired
private UserLoginFailureHandler userLoginFailureHandler;
@Autowired
private UserLogoutSuccessHandler userLogoutSuccessHandler;
@Autowired
private UserAuthenticationProvider userAuthenticationProvider;
@Autowired
private UserPermissionevaluator userPermissionevaluator;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public DefaultWebSecurityexpressionHandler userSecurityexpressionHandler() {
DefaultWebSecurityexpressionHandler handler = new DefaultWebSecurityexpressionHandler();
handler.setPermissionevaluator(userPermissionevaluator);
return handler;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(userAuthenticationProvider);
}
//@Value("${jwt.whiteList}")
private String whiteList = "zhangsan,lisi";//白名单,这里是不做验证的方法
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() // 权限配置
.antMatchers(whiteList.split(",")).permitAll()// 获取白名单(不进行权限验证)
//.anyRequest().authenticated() // 其他的需要登陆后才能访问
.and().httpBasic().authenticationEntryPoint(userNotLoginHandler) // 配置未登录处理类
.and().formLogin().loginProcessingUrl("/user/login")// 配置登录URL
//.and().formLogin().loginPage("/user/login")// 配置登录URL
.successHandler(userLoginSuccessHandler) // 配置登录成功处理类
.failureHandler(userLoginFailureHandler) // 配置登录失败处理类
.and().logout().logoutUrl("/logout/submit")// 配置登出地址
.logoutSuccessHandler(userLogoutSuccessHandler) // 配置用户登出处理类
.and().logout() //退出登录相关配置
.logoutSuccessUrl("/page/index") //退出成功后跳转的页面
.deletecookies("JSESSIONID") //退出时要删除的cookies的名字
.and().exceptionHandling().accessDeniedHandler(userAccessDeniedHandler)// 配置没有权限处理类
.and().cors()// 开启跨域
.and().csrf().disable(); // 禁用跨站请求伪造防护
//http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // 禁用session(使用Token认证)
//http.headers().cacheControl(); // 禁用缓存
//http.addFilter(new JWTAuthenticationFilter(authenticationManager())); 添加JWT过滤器,这一版就不写jtw取代session会话功能了
http.headers().frameOptions().disable();
}
}
14.Md5Util.java
package com.dev.config.security;
import java.security.MessageDigest;
public class Md5Util {
public final static String MD5(String s) {
char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
try {
// 密码+盐组合
byte[] btInput = s.getBytes();
// 获得MD5摘要算法的 MessageDigest 对象
MessageDigest mdInst = MessageDigest.getInstance("MD5");
// 使用指定的字节更新摘要
mdInst.update(btInput);
// 获得密文
byte[] md = mdInst.digest();
// 把密文转换成十六进制的字符串形式
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
String pwd = Md5Util.MD5("123456");
System.out.println(pwd );
}
}
15.SwaggerConfig.java
package com.dev.config;
import com.dev.App8080;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.documentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
@ConditionalOnWebApplication
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
List pars = new ArrayList<>();
ParameterBuilder token = new ParameterBuilder();
return new Docket(documentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage(App8080.class.getPackage().getName()))
.build()
.globalOperationParameters(pars)
.apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("SOD LRP Application Server RESTful API")
.version("1.0")
.build();
}
}
16.TSysUserController.java
package com.dev.controller;
import com.dev.common.Result;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
@Slf4j
@RequestMapping("tSysUser")
@RestController
@Api(value = "系统用户服务", tags = "系统用户服务")
public class TSysUserController {
@PreAuthorize("hasRole('ROLE_/tSysUser/findByPage')")
@PostMapping("findByPage")
@ApiOperation(value = "添加系统用户", notes = "添加系统用户", produces = "application/json")
public Result findByPage(){
log.info("测试用户分页查询权限");
return Result.success("测试用户分页查询权限");
}
@PreAuthorize("hasRole('ROLE_/tSysUser/add')")
@PostMapping("add")
@ApiOperation(value = "添加系统用户", notes = "添加系统用户", produces = "application/json")
public Result add(){
log.info("测试用户添加权限");
return Result.success("测试用户添加权限");
}
@PreAuthorize("hasRole('ROLE_/tSysUser/edit')")
@PostMapping("edit")
@ApiOperation(value = "添加系统用户", notes = "修改系统用户", produces = "application/json")
public Result edit(){
log.info("测试用户编辑权限");
return Result.success("测试用户编辑权限");
}
@PreAuthorize("hasRole('ROLE_/tSysUser/delete')")
@PostMapping("delete")
@ApiOperation(value = "删除系统用户", notes = "删除系统用户", produces = "application/json")
public Result delete(){
log.info("测试用户删除权限");
return Result.success("测试用户删除权限");
}
}
17.TSysResMapper.java
package com.dev.dao; import com.baomidou.mybatisplus.core.mapper.baseMapper; import com.dev.model.TSysRes; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import java.util.List; @Mapper public interface TSysResMapper extends baseMapper{ @Select("select " + " a.id, " + " a.name, " + " a.res_url, " + " a.permission, " + " a.res_type, " + " a.icon, " + " a.pid, " + " a.create_date " + "from " + " t_sys_res a " + "where a.res_type = '0' " + "order by a.create_date ") List findAllForAdminMenu(); }
18.TSysRoleMapper.java
package com.dev.dao; import com.baomidou.mybatisplus.core.mapper.baseMapper; import com.dev.model.TSysRole; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import java.util.List; @Mapper public interface TSysRoleMapper extends baseMapper{ @Select("SELECT r.* FROM t_sys_role r " + "LEFT JOIN t_sys_user_role ur ON ur.role_id = r.id " + "WHERe " + "ur.user_id = #{userId} ") List findRoleByUserId(String userId); }
19.TSysRoleResMapper.java
package com.dev.dao; import com.baomidou.mybatisplus.core.mapper.baseMapper; import com.dev.model.TSysRoleRes; import org.apache.ibatis.annotations.Mapper; import java.util.List; import java.util.Map; @Mapper public interface TSysRoleResMapper extends baseMapper{ List selectRoleResByMap(Map map); }
20.TSysUserMapper.java
package com.dev.dao; import com.baomidou.mybatisplus.core.mapper.baseMapper; import com.dev.model.TSysUser; import org.apache.ibatis.annotations.Mapper; @Mapper public interface TSysUserMapper extends baseMapper{ }
21.TSysUserRoleMapper.java
package com.dev.dao; import com.baomidou.mybatisplus.core.mapper.baseMapper; import com.dev.model.TSysUserRole; import org.apache.ibatis.annotations.Mapper; @Mapper public interface TSysUserRoleMapper extends baseMapper{ }
22.SysUserDetails.java
package com.dev.model;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.io.Serializable;
import java.util.Collection;
@Data
@EqualsAndHashCode(callSuper = false)
public class SysUserDetails extends TSysUser implements UserDetails, Serializable {
private static final long serialVersionUID = 1L;
private Collection authorities;
private boolean isAccountNonExpired = false;
private boolean isAccountNonLocked = false;
private boolean isCredentialsNonExpired = false;
private boolean isEnabled = true;
@Override
public Collection extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public boolean isAccountNonExpired() {
return isAccountNonExpired;
}
@Override
public boolean isAccountNonLocked() {
return isAccountNonLocked;
}
@Override
public boolean isCredentialsNonExpired() {
return isCredentialsNonExpired;
}
@Override
public boolean isEnabled() {
return isEnabled;
}
}
23.TSysRes.java
package com.dev.model;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
@Data
@TableName("t_sys_res")
public class TSysRes {
@TableId
private String id;//主键
private String name;//资源名称
private String resUrl;//资源路径
private String permission;//做拦截的code
private String resType;//0菜单 1按钮
private String pid;//父级id
private String icon;//菜单图标
private String createUser;//创建人
private Date createDate;//创建时间
}
24.TSysRole.java
import lombok.Data;
import java.util.Date;
@Data
@TableName("t_sys_role")
public class TSysRole {
@TableId
private String id;//主键
private String roleName;//角色名称
private String roleExplain;//角色描述
private String createUser;//创建人
private Date createDate;//创建时间
}
25.TSysRoleRes.java
package com.dev.model;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("t_sys_role_res")
public class TSysRoleRes {
@TableId
private String id;//主键
private String roleId;//角色id
private String resId;//资源id
}
26.TSysUser.java
package com.dev.model;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
@TableName("t_sys_user")
public class TSysUser implements Serializable {
private static final long serialVersionUID = 1L;
@TableId
private String id;//主键
private String username;//用户名
private String password;//密码
private String nickName;//昵称
private String cellPhone;//电话
private String mail;//邮件
private Date birthday;//生日
private String status;//状态(0-正常,1-禁用,2-删除)
private String accountType;//1系统账号 2客户账号
private String inviteCode;//邀请码
private String sex;//性别:0男 1女
private String address;//地址
private Integer upNum;//获赞总量
private Integer readNum;//文章被阅读总量
private String sign;//签名
private String pictureId;//用户头像
private String createUser;//创建人
private Date createDate;//创建时间
}
27.TSysUserRole.java
package com.dev.model;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("t_sys_user_role")
public class TSysUserRole {
@TableId
private String id;//主键
private String userId;//用户名id
private String roleId;//角色id
}
28.SysUserDetailsService.java
package com.dev.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dev.model.SysUserDetails;
import com.dev.model.TSysRes;
import com.dev.model.TSysUser;
import com.dev.dao.TSysResMapper;
import com.dev.service.TSysResService;
import com.dev.service.TSysUserService;
import com.github.pagehelper.util.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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;
import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Service
public class SysUserDetailsService implements UserDetailsService {
@Autowired
private TSysUserService tSysUserService;
@Resource
private TSysResMapper tSysResMapper;
@Autowired
private TSysResService tSysResService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
List resList = null;
if(username.equals("admin")){
TSysUser tSysUser = new TSysUser();
tSysUser.setId("admin");
tSysUser.setUsername("admin");
tSysUser.setNickName("系统管理员");
SysUserDetails sysUserDetails = new SysUserDetails();
BeanUtils.copyProperties(tSysUser, sysUserDetails);
Set authorities = new HashSet<>(); // 角色集合
//admin用户有的资源集合
resList = tSysResMapper.selectList(new QueryWrapper<>());
for (int i = 0; i < resList.size() ; i++) {
if(StringUtil.isNotEmpty(resList.get(i).getPermission())){
authorities.add(new SimpleGrantedAuthority("ROLE_" + resList.get(i).getPermission()));
}
}
sysUserDetails.setAuthorities(authorities);
return sysUserDetails;
}
TSysUser tSysUser = tSysUserService.findByUsername(username);
if (tSysUser != null) {
SysUserDetails sysUserDetails = new SysUserDetails();
BeanUtils.copyProperties(tSysUser, sysUserDetails);
Set authorities = new HashSet<>(); // 角色集合
resList = tSysResService.findResByUserId(sysUserDetails.getId());//当前用户有的资源集合
if(resList != null){
for (int i = 0; i < resList.size() ; i++) {
if(StringUtil.isNotEmpty(resList.get(i).getPermission())){
authorities.add(new SimpleGrantedAuthority("ROLE_" + resList.get(i).getPermission()));
}
}
}
sysUserDetails.setAuthorities(authorities);
return sysUserDetails;
}
return null;
}
}
29.TSysResServiceImpl.java
package com.dev.service.impl;
import com.dev.model.TSysRes;
import com.dev.model.TSysRole;
import com.dev.dao.TSysResMapper;
import com.dev.dao.TSysRoleMapper;
import com.dev.dao.TSysRoleResMapper;
import com.dev.service.TSysResService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class TSysResServiceImpl implements TSysResService {
@Resource
private TSysResMapper tSysResMapper;
@Resource
private TSysRoleMapper tSysRoleMapper;
@Resource
private TSysRoleResMapper tSysRoleResMapper;
@Override
public List findResByUserId(String userId) {
//获取用户有的角色
//根据当前登录用户获取角色
List roleList = tSysRoleMapper.findRoleByUserId(userId);
if(roleList == null || roleList.size() == 0){ //如果用户没有角色返回没有权限
return null;
}
//根据角色获取菜单资源id关系集合
Map map = new HashMap<>();
map.put("roleList",roleList);
List tSysRoleResList = tSysRoleResMapper.selectRoleResByMap(map);
if(tSysRoleResList == null || tSysRoleResList.size() == 0){ //如果用户没有角色返回没有权限
return null;
}
//根据资源id获取菜单资源
return tSysResMapper.selectBatchIds(tSysRoleResList);
}
}
30.TSysRoleResServiceImpl.java
package com.dev.service.impl;
import com.dev.service.TSysRoleResService;
import org.springframework.stereotype.Service;
@Service
public class TSysRoleResServiceImpl implements TSysRoleResService {
}
31.TSysRoleServiceImpl.java
package com.dev.service.impl;
import com.dev.service.TSysRoleService;
import org.springframework.stereotype.Service;
@Service
public class TSysRoleServiceImpl implements TSysRoleService {
}
32.TSysUserRoleServiceImpl.java
package com.dev.service.impl;
import com.dev.service.TSysUserRoleService;
import org.springframework.stereotype.Service;
@Service
public class TSysUserRoleServiceImpl implements TSysUserRoleService {
}
33.TSysUserServiceImpl.java
package com.dev.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dev.model.TSysUser;
import com.dev.dao.TSysUserMapper;
import com.dev.service.TSysUserService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class TSysUserServiceImpl implements TSysUserService {
@Resource
private TSysUserMapper tSysUserMapper;
public TSysUser findByUsername(String username) {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("username",username);
return tSysUserMapper.selectOne(queryWrapper);
}
}
34.TSysResService.java
package com.dev.service;
import com.dev.model.TSysRes;
import java.util.List;
public interface TSysResService {
List findResByUserId(String userId);
}
35.TSysRoleResService.java
package com.dev.service;
public interface TSysRoleResService {
}
36.TSysRoleService.java
package com.dev.service;
public interface TSysRoleService {
}
37.TSysUserRoleService.java
package com.dev.service;
public interface TSysUserRoleService {
}
38.TSysUserService.java
package com.dev.service;
import com.dev.model.TSysUser;
public interface TSysUserService {
TSysUser findByUsername(String username);
}
39.App8080.java
package com.dev;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class App8080 {
public static void main(String[] args) {
SpringApplication.run(App8080.class,args);
}
}
40.TSysRoleResMapper.xml
库表设计:
sql:直接导入数据库中行了,用户表密码是Md5加密, 密码为:123456
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for t_sys_res
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_res`;
CREATE TABLE `t_sys_res` (
`id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '资源id',
`name` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '资源名称',
`res_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '资源路径',
`permission` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '资源code',
`res_type` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '0菜单 1按钮',
`pid` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '父级id',
`create_user` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`create_date` datetime DEFAULT NULL,
`icon` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '菜单图标'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统-资源表【菜单】' ROW_FORMAT = Compact;
-- ----------------------------
-- Records of t_sys_res
-- ----------------------------
INSERT INTO `t_sys_res` VALUES ('101', '用户添加', '/tSysUser/add', '/tSysUser/add', '1', '100', NULL, NULL, '');
INSERT INTO `t_sys_res` VALUES ('100', '用户管理', '/tSysUser/findByPage', '/tSysUser/findByPage', '0', '', NULL, NULL, 'fa fa-snowflake-o');
INSERT INTO `t_sys_res` VALUES ('102', '用户修改', '/tSysUser/edit', '/tSysUser/edit', '1', '100', NULL, NULL, 'fa fa-home');
INSERT INTO `t_sys_res` VALUES ('103', '用户删除', '/tSysUser/delete', '/tSysUser/delete', '1', '100', NULL, NULL, 'fa fa-home');
-- ----------------------------
-- Table structure for t_sys_role
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_role`;
CREATE TABLE `t_sys_role` (
`id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色id',
`role_name` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色名称',
`role_explain` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '描述',
`create_user` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '创建人',
`create_date` datetime DEFAULT NULL COMMENT '创建时间'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统-角色表' ROW_FORMAT = Compact;
-- ----------------------------
-- Records of t_sys_role
-- ----------------------------
INSERT INTO `t_sys_role` VALUES ('277144172094291968', '部门经理', '部门经理', NULL, '2021-08-27 10:22:51');
INSERT INTO `t_sys_role` VALUES ('277144675716956160', '普通员工', '普通员工', NULL, '2021-08-27 10:24:51');
INSERT INTO `t_sys_role` VALUES ('277646459757658112', '测试员工', '测试员工', '', '2021-08-28 19:38:46');
-- ----------------------------
-- Table structure for t_sys_role_res
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_role_res`;
CREATE TABLE `t_sys_role_res` (
`id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键',
`role_id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色id',
`res_id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '资源id'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统-角色资源表中间表' ROW_FORMAT = Compact;
-- ----------------------------
-- Records of t_sys_role_res
-- ----------------------------
INSERT INTO `t_sys_role_res` VALUES ('1234', '277144675716956160', '101');
INSERT INTO `t_sys_role_res` VALUES ('12345', '277144675716956160', '100');
INSERT INTO `t_sys_role_res` VALUES ('123456', '277144172094291968', '100');
INSERT INTO `t_sys_role_res` VALUES ('123457', '277144172094291968', '101');
INSERT INTO `t_sys_role_res` VALUES ('123458', '277144172094291968', '102');
-- ----------------------------
-- Table structure for t_sys_user
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_user`;
CREATE TABLE `t_sys_user` (
`id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键',
`username` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名',
`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '密码',
`nick_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '昵称',
`cell_phone` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '手机号',
`mail` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '邮件',
`birthday` datetime DEFAULT NULL COMMENT '生日',
`status` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '状态(0-正常,1-删除,2-禁用)',
`account_type` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '1系统账号 2客户账号',
`invite_code` varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '邀请码',
`sex` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '性别:0男 1女',
`up_num` int(11) DEFAULT NULL COMMENT '所有获赞总量',
`read_num` int(11) DEFAULT NULL COMMENT '所有文章阅读总量',
`address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '地址',
`create_user` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '创建人',
`create_date` datetime DEFAULT NULL COMMENT '创建时间',
`sign` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '用户签名',
`picture_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '用户头像'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统-用户表' ROW_FORMAT = Compact;
-- ----------------------------
-- Records of t_sys_user
-- ----------------------------
INSERT INTO `t_sys_user` VALUES ('276866508766838784', 'liqingwei', 'E10ADC3949BA59ABBE56E057F20F883E', '李庆伟', '15801174628', 'liqingwei01@cnpc.cn', NULL, '0', '1', '3781941dd39446b89e98cb661766aade', NULL, 0, 0, NULL, NULL, '2021-08-26 15:59:31', NULL, NULL);
INSERT INTO `t_sys_user` VALUES ('277657251341139964', 'zhangsan', 'E10ADC3949BA59ABBE56E057F20F883E', '张三', '15801174626', 'zhangsan@qq.com', '2021-08-04 00:00:00', '0', '1', 'ea819ca462914e938943752d48ae8bcc', '0', 0, 0, '河南北京北', 'admin', '2021-08-28 20:21:38', '啥也不是。。。', '287348042074423296');
-- ----------------------------
-- Table structure for t_sys_user_role
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_user_role`;
CREATE TABLE `t_sys_user_role` (
`id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键',
`user_id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户id',
`role_id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色id',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统-用户角色中间表' ROW_FORMAT = Compact;
-- ----------------------------
-- Records of t_sys_user_role
-- ----------------------------
INSERT INTO `t_sys_user_role` VALUES ('111', '276866508766838784', '277144675716956160');
INSERT INTO `t_sys_user_role` VALUES ('222', '277657251341139964', '277144172094291968');
SET FOREIGN_KEY_CHECKS = 1;
测试:访问路径均为POST请求。
使用Postman测试 liqingwei用户
http://localhost:8080/user/login?username=liqingwei&password=123456
http://localhost:8080/tSysUser/findByPage
http://localhost:8080/tSysUser/edit
http://localhost:8080/tSysUser/delete
使用Postman测试 zhangsan用户
http://localhost:8080/user/login?username=zhangsan&password=123456
http://localhost:8080/tSysUser/findByPage
http://localhost:8080/tSysUser/edit
http://localhost:8080/tSysUser/delete
下篇博客更新Springboot+Security+JWT



