当前位置: 首页 > news >正文

网站主页模板 优帮云上海建设工程造价信息平台

网站主页模板 优帮云,上海建设工程造价信息平台,建网站英文,浙江网络推广公司目录 前言 数据库设计 用户表 角色表 用户角色表 权限表 角色权限表 插入数据 表的实体类 用户表实体类 角色表实体类 权限表实体类 mapper层接口 UserMapper RoleMapper AuthorityMapper 封装登录信息 统一响应结果 上下文相关类 jwt令牌工具类 依赖导入…目录 前言 数据库设计 用户表 角色表 用户角色表 权限表 角色权限表 插入数据 表的实体类 用户表实体类 角色表实体类 权限表实体类 mapper层接口 UserMapper RoleMapper AuthorityMapper 封装登录信息 统一响应结果 上下文相关类 jwt令牌工具类 依赖导入 属性类 yml配置文件 jwt令牌工具类 SpringContextUtils工具类  实现接口UserDetailsService 登录接口LoginController 自定义token验证过滤器 配置过滤器链 SecurityConfig完整配置 测试接口 开始测试 登录测试 权限测试 测试管理员权限访问 测试用户权限访问 总结 前言 接着《初识SpringSecurity》来看如何在项目中整合SpringSecurity这个安全框架。 https://blog.csdn.net/qq_74312711/article/details/134978245?spm1001.2014.3001.5501 上次我们是将用户添加到内存中实际开发中肯定是要存储在数据库里的。先来看数据库是如何设计的以及如何把用户信息交给Security处理。 数据库设计 用户表 存放用户信息主要是存放用户名和密码。 create table if not exists tb_user (id bigint auto_increment comment 主键primary key,username varchar(16) not null comment 用户名,password varchar(64) not null comment 密码,constraint usernameunique (username) )comment 用户表; 角色表 存放角色信息角色是用户的身份。 create table if not exists tb_role (id bigint auto_increment comment 主键primary key,role varchar(8) not null comment 角色,constraint roleunique (role) )comment 角色表; 用户角色表 用户和角色的关系一个用户可以有多个角色身份一个角色身份可以有多个用户对应。 create table if not exists tb_user_role (id bigint auto_increment comment 主键primary key,username varchar(16) not null comment 用户名;不唯一,role varchar(8) not null comment 角色;不唯一 )comment 用户角色表; 权限表 存放权限信息角色拥有权限。 create table if not exists tb_authority (id bigint auto_increment comment 主键primary key,authority varchar(16) not null comment 权限,constraint authorityunique (authority) )comment 权限表; 角色权限表 角色和权限的关系一个角色可以拥有多个权限一个权限可以被多个角色拥有。 create table if not exists tb_role_authority (id bigint auto_increment comment 主键primary key,role varchar(8) not null comment 角色;不唯一,authority varchar(16) not null comment 权限;不唯一 )comment 角色权限表; 插入数据 注意密码不能明文存储要先经过编码处理。 Test void getEncodePassword() {String password 123abc;BCryptPasswordEncoder bCryptPasswordEncoder new BCryptPasswordEncoder();String encode bCryptPasswordEncoder.encode(password);System.out.println(encode); // $2a$10$3OF9ij55dB7X2ffXby16Qu8n6Y96NV.RtHcza4vWO1EjoFO2JrsiW } insert into tb_user (id, username, password) values (null, 艾伦, $2a$10$3OF9ij55dB7X2ffXby16Qu8n6Y96NV.RtHcza4vWO1EjoFO2JrsiW);insert into tb_role (id, role) values (null, 管理员),(null, 用户);insert into tb_user_role (id, username, role) values (null, 艾伦, 管理员),(null, 艾伦, 用户);insert into tb_authority (id, authority) values (null, 权限1),(null, 权限2),(null, 权限3);insert into tb_role_authority (id, role, authority) values (null, 管理员, 权限1),(null, 管理员, 权限2),(null, 管理员, 权限3),(null, 用户, 权限1),(null, 用户, 权限2); 表的实体类 用户表实体类 import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;AllArgsConstructor Data NoArgsConstructor public class UserEntity {private Long id;private String username;private String password; } 角色表实体类 import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;AllArgsConstructor Data NoArgsConstructor public class RoleEntity {private Long id;private String role; } 权限表实体类 import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;AllArgsConstructor Data NoArgsConstructor public class AuthorityEntity {private Long id;private String authority; } mapper层接口 UserMapper import org.apache.ibatis.annotations.Mapper;Mapper public interface UserMapper {UserEntity selectUserByUsername(String username); } ?xml version1.0 encodingUTF-8 ? !DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtdmapper namespacecom.example.mapper.UserMapper!--查询用户--select idselectUserByUsername resultTypeUserEntityselect id, username, passwordfrom tb_userwhere username #{username};/select /mapper RoleMapper import org.apache.ibatis.annotations.Mapper;import java.util.List;Mapper public interface RoleMapper {ListRoleEntity selectRoleByUsername(String username); } ?xml version1.0 encodingUTF-8 ? !DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtdmapper namespacecom.example.mapper.RoleMapper!--查询角色--select idselectRoleByUsername resultTypeRoleEntityselect tr.id, tr.rolefrom tb_user_role turleft join tb_role tr on tur.role tr.rolewhere tur.username #{username};/select /mapper AuthorityMapper import org.apache.ibatis.annotations.Mapper;import java.util.List;Mapper public interface AuthorityMapper {ListAuthorityEntity selectAuthorityByRole(String role); } ?xml version1.0 encodingUTF-8 ? !DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtdmapper namespacecom.example.mapper.AuthorityMapper!--查询权限--select idselectAuthorityByRole resultTypeAuthorityEntityselect ta.id, ta.authorityfrom tb_role_authority traleft join tb_authority ta on tra.authority ta.authoritywhere tra.role #{role};/select /mapper 封装登录信息 登录请求必须要提供用户名、密码和角色后面都会用到。 import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;AllArgsConstructor Data NoArgsConstructor public class UserLogin {private String username;private String password;private String role; } 统一响应结果 import lombok.Data;import java.io.Serializable;Data public class ResultT implements Serializable {// 响应码1代表成功0代表失败private Integer code;// 提示信息private String message;// 响应数据private T data;public static T ResultT success() {ResultT result new Result();result.code 1;return result;}public static T ResultT success(T object) {ResultT result new Result();result.code 1;result.data object;return result;}public static T ResultT error(String message) {ResultT result new Result();result.code 0;result.message message;return result;} } 上下文相关类 ThreadLocal线程局部变量将信息放入上下文后面要用可以直接取出。 public class BaseContext {public static ThreadLocalString threadLocal new ThreadLocal();public static void setContext(String context) {threadLocal.set(context);}public static String getContext() {return threadLocal.get();}public static void removeContext() {threadLocal.remove();} } jwt令牌工具类 依赖导入 jwt令牌依赖 dependencygroupIdio.jsonwebtoken/groupIdartifactIdjjwt/artifactIdversion0.9.1/version /dependency 配置处理器依赖 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-configuration-processor/artifactIdoptionaltrue/optional /dependency 以下依赖必须导入否则jwt令牌用不了。  dependencygroupIdjavax.xml.bind/groupIdartifactIdjaxb-api/artifactIdversion2.3.1/version /dependency dependencygroupIdjavax.activation/groupIdartifactIdactivation/artifactIdversion1.1.1/version /dependency !-- no more than 2.3.3-- dependencygroupIdorg.glassfish.jaxb/groupIdartifactIdjaxb-runtime/artifactIdversion2.3.3/version /dependency 属性类 import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component;Data Component ConfigurationProperties(prefix token.jwt) public class JwtTokenProperties {// 签名密钥private String signingKey;// 有效时间private Long expire; } yml配置文件 token:jwt:signing-key: jwt-token-signing-key #签名密钥expire: 7200000 #有效时间 jwt令牌工具类 import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component;import java.util.Date; import java.util.Map;Component RequiredArgsConstructor public class JwtTokenUtils {private final JwtTokenProperties jwtTokenProperties;public String getJwtToken(MapString, Object claims) {String signingKey jwtTokenProperties.getSigningKey();Long expire jwtTokenProperties.getExpire();return Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS256, signingKey).setExpiration(new Date(System.currentTimeMillis() expire)).compact();}public Claims parseJwtToken(String jwtToken) {String signingKey jwtTokenProperties.getSigningKey();return Jwts.parser().setSigningKey(signingKey).parseClaimsJws(jwtToken).getBody();} } SpringContextUtils工具类  SpringContextUtils工具类用于在过滤器中获取Bean因为在过滤器中无法初始化Bean组件所以使用上下文获取。 import jakarta.annotation.Nonnull; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component;Component public class SpringContextUtils implements ApplicationContextAware {private static ApplicationContext applicationContext;public static ApplicationContext getApplicationContext() {return applicationContext;}Overridepublic void setApplicationContext(Nonnull ApplicationContext applicationContext) throws BeansException {SpringContextUtils.applicationContext applicationContext;}SuppressWarnings(unchecked)public static T T getBean(String name) throws BeansException {if (applicationContext null) {return null;}return (T) applicationContext.getBean(name);} } 实现接口UserDetailsService 实现UserDetailsService接口重写loadUserByUsername方法。方法返回一个User对象即为UserDetails对象。我们将用户的信息封装到User对象中返回给Security处理。 import lombok.RequiredArgsConstructor; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.stereotype.Service;import java.util.List; import java.util.StringJoiner;Service RequiredArgsConstructor public class UserLoginService implements UserDetailsService {private final UserMapper userMapper;private final RoleMapper roleMapper;private final AuthorityMapper authorityMapper;Overridepublic UserDetails loadUserByUsername(String username) {// 查询用户UserEntity userEntity userMapper.selectUserByUsername(username);if (userEntity null) {throw new RuntimeException(用户不存在);}// 获取用户登录身份roleString role BaseContext.getContext();ListRoleEntity roles roleMapper.selectRoleByUsername(username);// 判断用户是否有role身份boolean flag true;for (RoleEntity r : roles) {if (r.getRole().equals(role)) {flag false;break;}}if (flag) {throw new RuntimeException(用户 username 没有 role 身份);}// 查询角色权限ListAuthorityEntity authorities authorityMapper.selectAuthorityByRole(role);// 权限之间用,分隔StringJoiner stringJoiner new StringJoiner(,, , );authorities.forEach(authority - stringJoiner.add(authority.getAuthority()));return new User(userEntity.getUsername(), userEntity.getPassword(),AuthorityUtils.commaSeparatedStringToAuthorityList(stringJoiner.toString()));} } 登录接口LoginController 将角色信息放入上下文中在UserLoginService中会用到角色信息。 import lombok.RequiredArgsConstructor; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController;import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.StringJoiner;RestController RequiredArgsConstructor public class LoginController {private final UserLoginService userLoginService;private final JwtTokenUtils jwtTokenUtils;PostMapping(/login)public ResultString login(RequestBody UserLogin userLogin) {try {// 将登录用户角色放入上下文BaseContext.setContext(userLogin.getRole());UserDetails userDetails userLoginService.loadUserByUsername(userLogin.getUsername());// 获取用户权限StringJoiner authorityString new StringJoiner(,, , );Collection? extends GrantedAuthority authorities userDetails.getAuthorities();for (GrantedAuthority authority : authorities) {authorityString.add(authority.getAuthority());}MapString, Object claims new HashMap();claims.put(username, userLogin.getUsername());claims.put(role, userLogin.getRole());claims.put(authorityString, authorityString.toString());String jwtToken jwtTokenUtils.getJwtToken(claims);return Result.success(jwtToken);} catch (Exception e) {return Result.error(e.getMessage());}} } 自定义token验证过滤器 注意 1. 在过滤器中无法初始化Bean组件 2. 在过滤器中抛出的异常无法被全局异常处理器捕获 import com.fasterxml.jackson.databind.ObjectMapper; import io.jsonwebtoken.Claims; import jakarta.servlet.FilterChain; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils;import java.io.IOException;Component public class JwtAuthenticationFilter extends BasicAuthenticationFilter {public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {super(authenticationManager);}Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException {try {// 获取请求路径String url request.getRequestURL().toString();// 为登录请求放行if (url.contains(/login)) {filterChain.doFilter(request, response);return; // 结束方法}// 获取请求头中的tokenString jwtToken request.getHeader(token);if (!StringUtils.hasLength(jwtToken)) {// token不存在交给其他过滤器处理filterChain.doFilter(request, response);return; // 结束方法}// 过滤器中无法初始化Bean组件使用上下文获取JwtTokenUtils jwtTokenUtils SpringContextUtils.getBean(jwtTokenUtils);if (jwtTokenUtils null) {throw new RuntimeException();}// 解析jwt令牌Claims claims;try {claims jwtTokenUtils.parseJwtToken(jwtToken);} catch (Exception e) {throw new RuntimeException();}// 获取用户信息String username (String) claims.get(username); // 用户名String authorityString (String) claims.get(authorityString); // 权限Authentication authentication new UsernamePasswordAuthenticationToken(username, null,AuthorityUtils.commaSeparatedStringToAuthorityList(authorityString));// 将用户信息放入SecurityContext上下文SecurityContextHolder.getContext().setAuthentication(authentication);// 将用户名放入线程局部变量BaseContext.setContext(username);filterChain.doFilter(request, response);} catch (Exception e) {// 过滤器中抛出的异常无法被全局异常处理器捕获直接返回错误结果response.setCharacterEncoding(utf-8);response.setContentType(application/json; charsetutf-8);String value new ObjectMapper().writeValueAsString(Result.error(token验证失败));response.getWriter().write(value);}} } 配置过滤器链 注意给登录请求放行要不然访问不了登录接口。 // 配置过滤器链 Bean public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity httpSecurity) throws Exception {httpSecurity.authorizeHttpRequests(authorizeHttpRequests - authorizeHttpRequests.requestMatchers(HttpMethod.POST, /login).permitAll() // 登录请求放行.requestMatchers(HttpMethod.GET, /test1).hasAnyAuthority(权限1, 权限2).requestMatchers(HttpMethod.GET, /test2).hasAuthority(权限3));httpSecurity.authenticationProvider(authenticationProvider());// 禁用登录页面httpSecurity.formLogin(AbstractHttpConfigurer::disable);// 禁用登出页面httpSecurity.logout(AbstractHttpConfigurer::disable);// 禁用sessionhttpSecurity.sessionManagement(AbstractHttpConfigurer::disable);// 禁用httpBasichttpSecurity.httpBasic(AbstractHttpConfigurer::disable);// 禁用csrf保护httpSecurity.csrf(AbstractHttpConfigurer::disable);// 通过上下文获取AuthenticationManagerAuthenticationManager authenticationManager SpringContextUtils.getBean(authenticationManager);// 添加自定义token验证过滤器httpSecurity.addFilterBefore(new JwtAuthenticationFilter(authenticationManager), UsernamePasswordAuthenticationFilter.class);return httpSecurity.build(); } SecurityConfig完整配置 import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; 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.configurers.AbstractHttpConfigurer; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;Configuration EnableWebSecurity RequiredArgsConstructor public class SecurityConfig {private final UserDetailsService userDetailsService;// 加载用户信息Beanpublic UserDetailsService userDetailsService() {return userDetailsService;}// 身份验证管理器Beanpublic AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {return configuration.getAuthenticationManager();}// 处理身份验证Beanpublic AuthenticationProvider authenticationProvider() {DaoAuthenticationProvider daoAuthenticationProvider new DaoAuthenticationProvider();daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());daoAuthenticationProvider.setUserDetailsService(userDetailsService);return daoAuthenticationProvider;}// 密码编码器Beanpublic BCryptPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}// 配置过滤器链Beanpublic SecurityFilterChain defaultSecurityFilterChain(HttpSecurity httpSecurity) throws Exception {httpSecurity.authorizeHttpRequests(authorizeHttpRequests - authorizeHttpRequests.requestMatchers(HttpMethod.POST, /login).permitAll() // 登录请求放行.requestMatchers(HttpMethod.GET, /test1).hasAnyAuthority(权限1, 权限2).requestMatchers(HttpMethod.GET, /test2).hasAuthority(权限3));httpSecurity.authenticationProvider(authenticationProvider());// 禁用登录页面httpSecurity.formLogin(AbstractHttpConfigurer::disable);// 禁用登出页面httpSecurity.logout(AbstractHttpConfigurer::disable);// 禁用sessionhttpSecurity.sessionManagement(AbstractHttpConfigurer::disable);// 禁用httpBasichttpSecurity.httpBasic(AbstractHttpConfigurer::disable);// 禁用csrf保护httpSecurity.csrf(AbstractHttpConfigurer::disable);// 通过上下文获取AuthenticationManagerAuthenticationManager authenticationManager SpringContextUtils.getBean(authenticationManager);// 添加自定义token验证过滤器httpSecurity.addFilterBefore(new JwtAuthenticationFilter(authenticationManager), UsernamePasswordAuthenticationFilter.class);return httpSecurity.build();} } 测试接口 用户有权限访问/test1没有权限访问/test2。管理员有权限访问/test1和/test2。 import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;RestController public class DemoController {GetMapping(/test1)public String demo1() {System.out.println(test1访问成功);return test1访问成功;}GetMapping(/test2)public String demo2() {System.out.println(test2访问成功);return test2访问成功;} } 开始测试 登录测试 测试成功 权限测试 测试管理员权限访问 /test1访问成功 /test2测试成功 测试用户权限访问 用户登录 /test1访问成功 /test2访问失败 可以看到测试的结果都是正确的说明成功地实现了权限控制。 总结 以上就是如何在项目中整合SpringSecurity的基本用法我们再来看一下官方的描述 Spring Security是一个强大且高度可定制的身份验证和访问控制框架。它是保护基于Spring的应用程序的事实标准。 Spring Security是一个专注于为Java应用程序提供身份验证和授权的框架。与所有Spring项目一样Spring Security的真正力量在于它可以多么容易地扩展以满足自定义需求。 强大且高度可定制就是SpringSecurity受欢迎的关键我们还可以对以上的案例进行优化。例如我们不将用户角色的权限放在token令牌中而是放在Redis中。在进行token验证的时候解析出用户名拿用户名去Redis中找对应的权限。又或者我们可以自定义处理器处理用户未登录未携带token处理用户权限不足等。
http://www.yutouwan.com/news/347289/

相关文章:

  • xv10相同网站北京广告公司工资
  • wordpress 多语言建站为什么输入网址打开的却是别的网站
  • 松原公司做网站的流程wordpress宝塔伪静态
  • 使用word做网站网站这么上百度
  • 网站建设软著百度上搜不到网站
  • 集团网站设计建设做英文兼职的网站
  • 大连做网站 选领超科技宁波网站建设哪里有
  • 厦门汽车充电站建设报备网站wordpress博客栏目设计
  • 阿里巴巴的网站二维码怎么做域名注册网站哪个好
  • 青岛在线制作网站忻州企业网站建设
  • 三网合一网站 东莞南宁网站seo
  • 重庆建工集团建设网站优秀wordpress个人博客
  • wordpress建站的教程天华集团官网
  • 做企业网站需要什么条件中国建设银行春季招聘网站
  • jeecms做企业网站浙江的健康码小程序叫什么
  • 有哪些做统计销量的网站成都科技网站建设电话咨询
  • 网站排名优化服务如何形容一个网站做的好
  • 河北中太建设集团有限公司网站天猫商城支付方式
  • 建设法规的网站炫酷网站欣赏
  • 男女做视频网站秦皇岛网站开发
  • 保定 网站制作做一个app软件的步骤
  • 网站建设怎么做外国网站
  • 网站怎么找个人网站 免费
  • 免费的黄冈网站代码网站建设建站
  • 锦州网站设计骏域网站建设专家电话
  • 网站建设登录平板怎么做网页
  • 网站开发 会费管理 模块网站是怎么做新手引导
  • 为什么自己做的网站老是404错误做网站有必要要源码吗
  • 国内做网站建设知名的公司互联网产品运营是做什么的
  • 咸宁公司做网站网站外链平台