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

咖啡店网站首页怎么做兰州再次出台9条优化措施

咖啡店网站首页怎么做,兰州再次出台9条优化措施,手机上登录qq网页版,高中同步测控优化设计答案SpringSecurity和JWT实现认证和授权 框架介绍SpringSecurityJWT组成实例JWT实现认证和授权的原理 Hutool 使用表整合SpringSecurity及JWT在pom.xml中添加依赖添加JWT token的工具类添加RbacAdminService#xff1a;添加自定义mapper创建SpringSecurity配置类添加ProjectSecuri… SpringSecurity和JWT实现认证和授权 框架介绍SpringSecurityJWT组成实例JWT实现认证和授权的原理 Hutool 使用表整合SpringSecurity及JWT在pom.xml中添加依赖添加JWT token的工具类添加RbacAdminService添加自定义mapper创建SpringSecurity配置类添加ProjectSecurityConfig添加JwtAuthenticationTokenFilter添加congtroller修改Swagger的配置 认证与授权流程演示运行项目访问API未登录时访问接口登录后访问接口改用其他有权限的帐号登录 总结源码 本文主要讲解SpringBoot项目通过整合SpringSecurity和JWT实现后台用户的登录和授权功能同时使用Swagger-UI使其可以自动记住登录令牌进行发送。 框架介绍 SpringSecurity SpringSecurity是一个强大的可高度定制的认证和授权框架对于Spring应用来说它是一套Web安全标准。SpringSecurity注重于为Java应用提供认证和授权功能像所有的Spring项目一样它对自定义需求具有强大的扩展性。 JWT JWT是JSON WEB TOKEN的缩写它是基于 RFC 7519 标准定义的一种可以安全传输的的JSON对象由于使用了数字签名所以是可信任和安全的。 组成 JWT token的格式header.payload.signatureheader中用于存放签名的生成算法 {alg: HS512}payload中用于存放用户名、token的生成时间和过期时间 {sub:admin,created:1489079981393,exp:1489684781}signature为以header和payload生成的签名一旦header和payload被篡改验证将失败 //secret为加密算法的密钥 String signature HMACSHA512(base64UrlEncode(header) . base64UrlEncode(payload),secret)实例 这是一个JWT的字符串 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c使用线上解析工具https://jwt.io/ JWT实现认证和授权的原理 用户调用登录接口登录成功后获取到JWT的token之后用户每次调用接口都在http的header中添加一个叫Authorization的头值为JWT的token后台程序通过对Authorization头中信息的解码及数字签名校验来获取其中的用户信息从而实现认证和授权。 Hutool Hutool是一个丰富的Java开源工具包,它帮助我们简化每一行代码减少每一个方法mall项目采用了此工具包。 使用表 pms_brand品牌表 rbac_admin后台用户表 rbac_role后台用户角色表 rbac_permission后台用户权限表 rbac_admin_role_relation后台用户和角色关系表用户与角色是多对多关系 rbac_role_permission_relation后台用户角色和权限关系表角色与权限是多对多关系 rbac_admin_permission_relation后台用户和权限关系表(除角色中定义的权限以外的加减权限)加权限是指用户比角色多出的权限减权限是指用户比角色少的权限 CREATE TABLE pms_brand (id bigint NOT NULL AUTO_INCREMENT,name varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,first_letter varchar(8) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 首字母,sort int DEFAULT NULL,factory_status int DEFAULT NULL COMMENT 是否为品牌制造商0-不是1-是,show_status int DEFAULT NULL,product_count int DEFAULT NULL COMMENT 产品数量,product_comment_count int DEFAULT NULL COMMENT 产品评论数量,logo varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 品牌logo,big_pic varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 专区大图,brand_story text CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci COMMENT 品牌故事,PRIMARY KEY (id) USING BTREE ) ENGINEInnoDB AUTO_INCREMENT71 DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci ROW_FORMATDYNAMIC COMMENT品牌表;CREATE TABLE rbac_admin (id bigint NOT NULL AUTO_INCREMENT,username varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,password varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,icon varchar(500) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 头像,email varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 邮箱,nick_name varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 昵称,note varchar(500) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 备注信息,create_time datetime DEFAULT NULL COMMENT 创建时间,login_time datetime DEFAULT NULL COMMENT 最后登录时间,status int DEFAULT 1 COMMENT 帐号启用状态0-禁用1-启用,PRIMARY KEY (id) USING BTREE ) ENGINEInnoDB AUTO_INCREMENT18 DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci ROW_FORMATDYNAMIC COMMENT后台用户表;CREATE TABLE rbac_role (id bigint NOT NULL AUTO_INCREMENT,name varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 名称,description varchar(500) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 描述,admin_count int DEFAULT NULL COMMENT 后台用户数量,create_time datetime DEFAULT NULL COMMENT 创建时间,status int DEFAULT 1 COMMENT 启用状态0-禁用1-启用,sort int DEFAULT 0,PRIMARY KEY (id) USING BTREE ) ENGINEInnoDB AUTO_INCREMENT9 DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci ROW_FORMATDYNAMIC COMMENT后台用户角色表;CREATE TABLE rbac_permission (id bigint NOT NULL AUTO_INCREMENT,pid bigint DEFAULT NULL COMMENT 父级权限id,name varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 名称,value varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 权限值,icon varchar(500) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 图标,type int DEFAULT NULL COMMENT 权限类型0-目录1-菜单2-按钮接口绑定权限,uri varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 前端资源路径,status int DEFAULT NULL COMMENT 启用状态0-禁用1-启用,create_time datetime DEFAULT NULL COMMENT 创建时间,sort int DEFAULT NULL COMMENT 排序,PRIMARY KEY (id) USING BTREE ) ENGINEInnoDB AUTO_INCREMENT37 DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci ROW_FORMATDYNAMIC COMMENT后台用户权限表;CREATE TABLE rbac_admin_permission_relation (id bigint NOT NULL AUTO_INCREMENT,admin_id bigint DEFAULT NULL,permission_id bigint DEFAULT NULL,type int DEFAULT NULL,PRIMARY KEY (id) USING BTREE ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci ROW_FORMATDYNAMIC COMMENT后台用户和权限关系表(除角色中定义的权限以外的加减权限);CREATE TABLE rbac_admin_role_relation (id bigint NOT NULL AUTO_INCREMENT,admin_id bigint DEFAULT NULL,role_id bigint DEFAULT NULL,PRIMARY KEY (id) USING BTREE ) ENGINEInnoDB AUTO_INCREMENT38 DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci ROW_FORMATDYNAMIC COMMENT后台用户和角色关系表;CREATE TABLE rbac_role_permission_relation (id bigint NOT NULL AUTO_INCREMENT,role_id bigint DEFAULT NULL,permission_id bigint DEFAULT NULL,PRIMARY KEY (id) USING BTREE ) ENGINEInnoDB AUTO_INCREMENT37 DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci ROW_FORMATDYNAMIC COMMENT后台用户角色和权限关系表; 自行插入几条数据做好用户、角色和权限关系对应用户可以使用功能的注册接口因为密码需要加密 整合SpringSecurity及JWT 在pom.xml中添加依赖 !--SpringSecurity依赖配置-- dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-security/artifactId /dependency !--Hutool Java工具包-- dependencygroupIdcn.hutool/groupIdartifactIdhutool-all/artifactIdversion4.5.7/version /dependency !--JWT(Json Web Token)登录支持-- dependencygroupIdio.jsonwebtoken/groupIdartifactIdjjwt/artifactIdversion0.9.0/version /dependency SpringBoot 2.6.0以上版本需要加个这个依赖 dependencygroupIdjavax.xml.bind/groupIdartifactIdjaxb-api/artifactIdversion2.3.1/version /dependencySpringBoot 2.6.0以上版本使用的swagger是3.0.0版本 !-- Swagger3 --dependencygroupIdio.springfox/groupIdartifactIdspringfox-boot-starter/artifactIdversion3.0.0/version/dependency!--Swagger-UI API文档生产工具--dependencygroupIdio.springfox/groupIdartifactIdspringfox-swagger2/artifactIdversion3.0.0/version/dependencydependencygroupIdio.springfox/groupIdartifactIdspringfox-swagger-ui/artifactIdversion3.0.0/version/dependency添加JWT token的工具类 用于生成和解析JWT token的工具类 相关方法说明 generateToken(UserDetails userDetails) :用于根据登录用户信息生成tokengetUserNameFromToken(String token)从token中获取登录用户的信息validateToken(String token, UserDetails userDetails)判断token是否还有效 先添加yml配置 server:port: 8080spring:datasource:url: jdbc:mysql://localhost:3306/mybatis?useUnicodetruecharacterEncodingutf-8serverTimezoneAsia/ShanghaiuseSSLfalseusername: rootpassword: rootmvc:pathmatch:matching-strategy: ant_path_matchermybatis:mapper-locations:- classpath:dao/*.xml- classpath*:com/**/mapper/*.xml logging:level:root: infocom.sheep: debug # 自定义jwt key jwt:tokenHeader: Authorization #JWT存储的请求头secret: mySecret #JWT加解密使用的密钥expiration: 604800 #JWT的超期限时间(60*60*24)tokenHead: Bearer #JWT负载中拿到开头secure:ignored:urls: #安全路径白名单- /swagger-ui/- /swagger-resources/**- /**/v2/api-docs- /**/*.html- /**/*.js- /**/*.css- /**/*.png- /favicon.ico- /actuator/**- /druid/**- /admin/**import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Component; import org.slf4j.Logger; import org.slf4j.LoggerFactory;import java.util.Date; import java.util.HashMap; import java.util.Map;/*** JwtToken生成的工具类*/ Component public class JwtTokenUtil {private static final Logger LOGGER LoggerFactory.getLogger(JwtTokenUtil.class);private static final String CLAIM_KEY_USERNAME sub;private static final String CLAIM_KEY_CREATED created;Value(${jwt.secret})private String secret;Value(${jwt.expiration})private Long expiration;/*** 根据负责生成JWT的token*/private String generateToken(MapString, Object claims) {return Jwts.builder().setClaims(claims).setExpiration(generateExpirationDate()).signWith(SignatureAlgorithm.HS512, secret).compact();}/*** 从token中获取JWT中的负载*/private Claims getClaimsFromToken(String token) {Claims claims null;try {claims Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();} catch (Exception e) {LOGGER.info(JWT格式验证失败:{}, token);}return claims;}/*** 生成token的过期时间*/private Date generateExpirationDate() {return new Date(System.currentTimeMillis() expiration * 1000);}/*** 从token中获取登录用户名*/public String getUserNameFromToken(String token) {String username;try {Claims claims getClaimsFromToken(token);username claims.getSubject();} catch (Exception e) {username null;}return username;}/*** 验证token是否还有效** param token 客户端传入的token* param userDetails 从数据库中查询出来的用户信息*/public boolean validateToken(String token, UserDetails userDetails) {String username getUserNameFromToken(token);return username.equals(userDetails.getUsername()) !isTokenExpired(token);}/*** 判断token是否已经失效*/private boolean isTokenExpired(String token) {Date expiredDate getExpiredDateFromToken(token);return expiredDate.before(new Date());}/*** 从token中获取过期时间*/private Date getExpiredDateFromToken(String token) {Claims claims getClaimsFromToken(token);return claims.getExpiration();}/*** 根据用户信息生成token*/public String generateToken(UserDetails userDetails) {MapString, Object claims new HashMap();claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername());claims.put(CLAIM_KEY_CREATED, new Date());return generateToken(claims);}/*** 判断token是否可以被刷新*/public boolean canRefresh(String token) {return !isTokenExpired(token);}/*** 刷新token*/public String refreshToken(String token) {Claims claims getClaimsFromToken(token);claims.put(CLAIM_KEY_CREATED, new Date());return generateToken(claims);} }使用Mybatis Generator生成相关表的model mapper代码使用方式参考链接: MyBatis Generator使用总结 生成如图代码 添加RbacAdminService public interface RbacAdminService {/*** 根据用户名获取后台管理员*/RbacAdmin getAdminByUsername(String username);UserDetails loadUserByUsername(String username);/*** 注册功能*/RbacAdmin register(RbacAdmin umsAdminParam);/*** 登录功能** param username 用户名* param password 密码* return 生成的JWT的token*/String login(String username, String password);/*** 获取用户所有权限包括角色权限和-权限*/ListRbacPermission getPermissionList(Long adminId); }Service public class RbacAdminServiceImpl implements RbacAdminService {private static final Logger LOGGER LoggerFactory.getLogger(RbacAdminServiceImpl.class);Autowiredprivate JwtTokenUtil jwtTokenUtil;Autowiredprivate PasswordEncoder passwordEncoder;Value(${jwt.tokenHead})private String tokenHead;Autowiredprivate RbacAdminMapper adminMapper;Autowiredprivate RbacAdminRoleRelationDao adminRoleRelationDao;Overridepublic RbacAdmin getAdminByUsername(String username) {RbacAdminExample example new RbacAdminExample();example.createCriteria().andUsernameEqualTo(username);ListRbacAdmin adminList adminMapper.selectByExample(example);if (adminList ! null adminList.size() 0) {return adminList.get(0);}return null;}Overridepublic UserDetails loadUserByUsername(String username) {//获取用户信息RbacAdmin admin getAdminByUsername(username);if (admin ! null) {ListRbacPermission permissionList getPermissionList(admin.getId());return new AdminUserDetails(admin, permissionList);}throw new UsernameNotFoundException(用户名或密码错误);}Overridepublic RbacAdmin register(RbacAdmin umsAdminParam) {RbacAdmin rbacAdmin new RbacAdmin();BeanUtils.copyProperties(umsAdminParam, rbacAdmin);rbacAdmin.setCreateTime(new Date());rbacAdmin.setStatus(1);//查询是否有相同用户名的用户RbacAdminExample example new RbacAdminExample();example.createCriteria().andUsernameEqualTo(rbacAdmin.getUsername());ListRbacAdmin umsAdminList adminMapper.selectByExample(example);if (umsAdminList.size() 0) {return null;}//将密码进行加密操作String encodePassword passwordEncoder.encode(rbacAdmin.getPassword());rbacAdmin.setPassword(encodePassword);adminMapper.insert(rbacAdmin);return rbacAdmin;}Overridepublic String login(String username, String password) {String token null;//密码需要客户端加密后传递try {UserDetails userDetails loadUserByUsername(username);if (!passwordEncoder.matches(password, userDetails.getPassword())) {throw new RuntimeException(密码不正确);}if (!userDetails.isEnabled()) {throw new RuntimeException(帐号已被禁用);}UsernamePasswordAuthenticationToken authentication new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());SecurityContextHolder.getContext().setAuthentication(authentication);token jwtTokenUtil.generateToken(userDetails);updateLoginTimeByUsername(username);} catch (AuthenticationException e) {LOGGER.warn(登录异常:{}, e.getMessage());}return token;}/*** 根据用户名修改登录时间*/private void updateLoginTimeByUsername(String username) {RbacAdmin record new RbacAdmin();record.setLoginTime(new Date());RbacAdminExample example new RbacAdminExample();example.createCriteria().andUsernameEqualTo(username);adminMapper.updateByExampleSelective(record, example);}Overridepublic ListRbacPermission getPermissionList(Long adminId) {return adminRoleRelationDao.getPermissionList(adminId);} }添加自定义mapper RbacAdminRoleRelationDao 获取用户所有权限 public interface RbacAdminRoleRelationDao {/*** 获取用户所有权限(包括-权限)*/ListRbacPermission getPermissionList(Param(adminId) Long adminId); }?xml version1.0 encodingUTF-8? !DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespacecom.sheep.dao.RbacAdminRoleRelationDaoselect idgetPermissionList resultMapcom.sheep.mbg.mapper.RbacPermissionMapper.BaseResultMapSELECTp.*FROMrbac_admin_role_relation arLEFT JOIN rbac_role r ON ar.role_id r.idLEFT JOIN rbac_role_permission_relation rp ON r.id rp.role_idLEFT JOIN rbac_permission p ON rp.permission_id p.idWHEREar.admin_id #{adminId}AND p.id IS NOT NULLAND p.id NOT IN (SELECTp.idFROMrbac_admin_permission_relation prLEFT JOIN rbac_permission p ON pr.permission_id p.idWHEREpr.type - 1AND pr.admin_id #{adminId})UNIONSELECTp.*FROMrbac_admin_permission_relation prLEFT JOIN rbac_permission p ON pr.permission_id p.idWHEREpr.type 1AND pr.admin_id #{adminId}/select /mapper创建SpringSecurity配置类 dto包下创建一个AdminUserDetails SpringSecurity需要的用户详情 public class AdminUserDetails implements UserDetails {private RbacAdmin umsAdmin;private ListRbacPermission permissionList;public AdminUserDetails(RbacAdmin umsAdmin, ListRbacPermission permissionList) {this.umsAdmin umsAdmin;this.permissionList permissionList;}Overridepublic Collection? extends GrantedAuthority getAuthorities() {//返回当前用户的权限return permissionList.stream().filter(permission - permission.getValue()!null).map(permission -new SimpleGrantedAuthority(permission.getValue())).collect(Collectors.toList());}Overridepublic String getPassword() {return umsAdmin.getPassword();}Overridepublic String getUsername() {return umsAdmin.getUsername();}Overridepublic boolean isAccountNonExpired() {return true;}Overridepublic boolean isAccountNonLocked() {return true;}Overridepublic boolean isCredentialsNonExpired() {return true;}Overridepublic boolean isEnabled() {return umsAdmin.getStatus().equals(1);} } 添加 SecurityConfig Configuration EnableWebSecurity EnableGlobalMethodSecurity(prePostEnabled true) public class SecurityConfig {Autowiredprivate RestfulAccessDeniedHandler restfulAccessDeniedHandler;Autowiredprivate RestAuthenticationEntryPoint restAuthenticationEntryPoint;Autowiredprivate IgnoreUrlsConfig ignoreUrlsConfig;BeanSecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {ExpressionUrlAuthorizationConfigurerHttpSecurity.ExpressionInterceptUrlRegistry registry httpSecurity.authorizeRequests();//不需要保护的资源路径允许访问for (String url : ignoreUrlsConfig.getUrls()) {registry.antMatchers(url).permitAll();}//允许跨域请求的OPTIONS请求registry.antMatchers(HttpMethod.OPTIONS).permitAll();httpSecurity.csrf()// 由于使用的是JWT我们这里不需要csrf.disable().sessionManagement()// 基于token所以不需要session.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests().anyRequest()// 除上面外的所有请求全部需要鉴权认证.authenticated();// 禁用缓存httpSecurity.headers().cacheControl();// 添加JWT filterhttpSecurity.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);//添加自定义未授权和未登录结果返回httpSecurity.exceptionHandling().accessDeniedHandler(restfulAccessDeniedHandler).authenticationEntryPoint(restAuthenticationEntryPoint);return httpSecurity.build();}Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}Beanpublic JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() {return new JwtAuthenticationTokenFilter();}} IgnoreUrlsConfig 配置访问权限白名单 Configuration ConfigurationProperties(prefix secure.ignored) public class IgnoreUrlsConfig {private ListString urls new ArrayList();public ListString getUrls() {return urls;}public void setUrls(ListString urls) {this.urls urls;} }其中 RestAuthenticationEntryPoint 是 当未登录或者token失效访问接口时自定义的返回结果 /*** 当未登录或者token失效访问接口时自定义的返回结果*/ Component public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {response.setCharacterEncoding(UTF-8);response.setContentType(application/json);response.getWriter().println(JSONUtil.parse(CommonResult.unauthorized(authException.getMessage())));response.getWriter().flush();} }RestfulAccessDeniedHandler 是 当访问接口没有权限时自定义的返回结果 /*** 当访问接口没有权限时自定义的返回结果*/ Component public class RestfulAccessDeniedHandler implements AccessDeniedHandler{Overridepublic void handle(HttpServletRequest request,HttpServletResponse response,AccessDeniedException e) throws IOException, ServletException {response.setCharacterEncoding(UTF-8);response.setContentType(application/json);response.getWriter().println(JSONUtil.parse(CommonResult.forbidden(e.getMessage())));response.getWriter().flush();} }相关依赖及方法说明 configure(HttpSecurity httpSecurity)用于配置需要拦截的url路径、jwt过滤器及出异常后的处理器configure(AuthenticationManagerBuilder auth)用于配置UserDetailsService及PasswordEncoderRestfulAccessDeniedHandler当用户没有访问权限时的处理器用于返回JSON格式的处理结果RestAuthenticationEntryPoint当未登录或token失效时返回JSON格式的结果UserDetailsService:SpringSecurity定义的核心接口用于根据用户名获取用户信息需要自行实现UserDetailsSpringSecurity定义用于封装用户信息的类主要是用户信息和权限需要自行实现PasswordEncoderSpringSecurity定义的用于对密码进行编码及比对的接口目前使用的是BCryptPasswordEncoderJwtAuthenticationTokenFilter在用户名和密码校验前添加的过滤器如果有jwt的token会自行根据token信息进行登录 添加ProjectSecurityConfig Configuration public class ProjectSecurityConfig {Autowiredprivate RbacAdminService adminService;Beanpublic UserDetailsService userDetailsService() {//获取登录用户信息return username - {UserDetails admin adminService.loadUserByUsername(username);if (admin ! null) {return admin;}throw new UsernameNotFoundException(用户名或密码错误);};} }添加JwtAuthenticationTokenFilter 在用户名和密码校验前添加的过滤器如果请求中有jwt的token且有效会取出token中的用户名然后调用SpringSecurity的API进行登录操作。 /*** JWT登录授权过滤器*/ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {private static final Logger LOGGER LoggerFactory.getLogger(JwtAuthenticationTokenFilter.class);Autowiredprivate UserDetailsService userDetailsService;Autowiredprivate JwtTokenUtil jwtTokenUtil;Value(${jwt.tokenHeader})private String tokenHeader;Value(${jwt.tokenHead})private String tokenHead;Overrideprotected void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain chain) throws ServletException, IOException {String authHeader request.getHeader(this.tokenHeader);if (authHeader ! null authHeader.startsWith(this.tokenHead)) {String authToken authHeader.substring(this.tokenHead.length());// The part after Bearer String username jwtTokenUtil.getUserNameFromToken(authToken);LOGGER.info(checking username:{}, username);if (username ! null SecurityContextHolder.getContext().getAuthentication() null) {UserDetails userDetails this.userDetailsService.loadUserByUsername(username);if (jwtTokenUtil.validateToken(authToken, userDetails)) {UsernamePasswordAuthenticationToken authentication new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));LOGGER.info(authenticated user:{}, username);SecurityContextHolder.getContext().setAuthentication(authentication);}}}chain.doFilter(request, response);} }添加congtroller /*** 后台用户管理*/ Controller Api(tags RbacAdminController, description 后台用户管理) RequestMapping(/admin) public class RbacAdminController {Autowiredprivate RbacAdminService adminService;Value(${jwt.tokenHeader})private String tokenHeader;Value(${jwt.tokenHead})private String tokenHead;ApiOperation(value 用户注册)RequestMapping(value /register, method RequestMethod.POST)ResponseBodypublic CommonResultRbacAdmin register(RequestBody RbacAdmin umsAdminParam, BindingResult result) {RbacAdmin umsAdmin adminService.register(umsAdminParam);if (umsAdmin null) {CommonResult.failed();}return CommonResult.success(umsAdmin);}ApiOperation(value 登录以后返回token)RequestMapping(value /login, method RequestMethod.POST)ResponseBodypublic CommonResult login(RequestBody RbacAdminLoginParam rbacAdminLoginParam, BindingResult result) {String token adminService.login(rbacAdminLoginParam.getUsername(), rbacAdminLoginParam.getPassword());if (token null) {return CommonResult.validateFailed(用户名或密码错误);}MapString, String tokenMap new HashMap();tokenMap.put(token, token);tokenMap.put(tokenHead, tokenHead);return CommonResult.success(tokenMap);}ApiOperation(获取用户所有权限包括-权限)RequestMapping(value /permission/{adminId}, method RequestMethod.GET)ResponseBodypublic CommonResultListRbacPermission getPermissionList(PathVariable Long adminId) {ListRbacPermission permissionList adminService.getPermissionList(adminId);return CommonResult.success(permissionList);} }品牌表的service接口 public interface PmsBrandService {ListPmsBrand listAllBrand();int createBrand(PmsBrand brand);int updateBrand(Long id, PmsBrand brand);int deleteBrand(Long id);ListPmsBrand listBrand(int pageNum, int pageSize);PmsBrand getBrand(Long id); }/*** PmsBrandService实现类*/ Service public class PmsBrandServiceImpl implements PmsBrandService {Autowiredprivate PmsBrandMapper brandMapper;Overridepublic ListPmsBrand listAllBrand() {return brandMapper.selectByExample(new PmsBrandExample());}Overridepublic int createBrand(PmsBrand brand) {return brandMapper.insertSelective(brand);}Overridepublic int updateBrand(Long id, PmsBrand brand) {brand.setId(id);return brandMapper.updateByPrimaryKeySelective(brand);}Overridepublic int deleteBrand(Long id) {return brandMapper.deleteByPrimaryKey(id);}Overridepublic ListPmsBrand listBrand(int pageNum, int pageSize) {PageHelper.startPage(pageNum, pageSize);return brandMapper.selectByExample(new PmsBrandExample());}Overridepublic PmsBrand getBrand(Long id) {return brandMapper.selectByPrimaryKey(id);} }品牌管理Controller用于测试授权和权限认证 /*** 品牌管理Controller*/ Api(tags PmsBrandController, description 商品品牌管理) Controller RequestMapping(/brand) public class PmsBrandController {Autowiredprivate PmsBrandService brandService;private static final Logger LOGGER LoggerFactory.getLogger(PmsBrandController.class);ApiOperation(获取所有品牌列表)RequestMapping(value listAll, method RequestMethod.GET)ResponseBodyPreAuthorize(hasAuthority(pms:brand:read))public CommonResultListPmsBrand getBrandList() {return CommonResult.success(brandService.listAllBrand());}ApiOperation(添加品牌)RequestMapping(value /create, method RequestMethod.POST)ResponseBodypublic CommonResult createBrand(RequestBody PmsBrand pmsBrand) {CommonResult commonResult;int count brandService.createBrand(pmsBrand);if (count 1) {commonResult CommonResult.success(pmsBrand);LOGGER.debug(createBrand success:{}, pmsBrand);} else {commonResult CommonResult.failed(操作失败);LOGGER.debug(createBrand failed:{}, pmsBrand);}return commonResult;}ApiOperation(更新指定id品牌信息)RequestMapping(value /update/{id}, method RequestMethod.POST)ResponseBodypublic CommonResult updateBrand(PathVariable(id) Long id, RequestBody PmsBrand pmsBrandDto, BindingResult result) {CommonResult commonResult;int count brandService.updateBrand(id, pmsBrandDto);if (count 1) {commonResult CommonResult.success(pmsBrandDto);LOGGER.debug(updateBrand success:{}, pmsBrandDto);} else {commonResult CommonResult.failed(操作失败);LOGGER.debug(updateBrand failed:{}, pmsBrandDto);}return commonResult;}ApiOperation(删除指定id的品牌)RequestMapping(value /delete/{id}, method RequestMethod.GET)ResponseBodypublic CommonResult deleteBrand(PathVariable(id) Long id) {int count brandService.deleteBrand(id);if (count 1) {LOGGER.debug(deleteBrand success :id{}, id);return CommonResult.success(null);} else {LOGGER.debug(deleteBrand failed :id{}, id);return CommonResult.failed(操作失败);}}ApiOperation(分页查询品牌列表)RequestMapping(value /list, method RequestMethod.GET)ResponseBodypublic CommonResultCommonPagePmsBrand listBrand(RequestParam(value pageNum, defaultValue 1)ApiParam(页码) Integer pageNum,RequestParam(value pageSize, defaultValue 3)ApiParam(每页数量) Integer pageSize) {ListPmsBrand brandList brandService.listBrand(pageNum, pageSize);return CommonResult.success(CommonPage.restPage(brandList));}ApiOperation(获取指定id的品牌详情)RequestMapping(value /{id}, method RequestMethod.GET)ResponseBodypublic CommonResultPmsBrand brand(PathVariable(id) Long id) {return CommonResult.success(brandService.getBrand(id));} } 修改Swagger的配置 通过修改配置实现调用接口自带Authorization头这样就可以访问需要登录的接口了。 /*** Swagger2API文档的配置*/ Configuration public class Swagger2Config {Beanpublic Docket createRestApi() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()//为当前包下controller生成API文档.apis(RequestHandlerSelectors.basePackage(com.sheep.controller)).paths(PathSelectors.any()).build()//添加登录认证.securitySchemes(securitySchemes()).securityContexts(securityContexts());}private ApiInfo apiInfo() {return new ApiInfoBuilder().title(SwaggerUI演示).description(learn-SecurityAndJWT).contact(new Contact(learn-SecurityAndJWT,null,null)).version(1.0).build();}private ListSecurityScheme securitySchemes() {//设置请求头信息ListSecurityScheme result new ArrayList();ApiKey apiKey new ApiKey(Authorization, Authorization, header);result.add(apiKey);return result;}private ListSecurityContext securityContexts() {//设置需要登录认证的路径ListSecurityContext result new ArrayList();result.add(getContextByPath(/brand/.*));return result;}private SecurityContext getContextByPath(String pathRegex) {return SecurityContext.builder().securityReferences(defaultAuth()).forPaths(PathSelectors.regex(pathRegex)).build();}private ListSecurityReference defaultAuth() {ListSecurityReference result new ArrayList();AuthorizationScope authorizationScope new AuthorizationScope(global, accessEverything);AuthorizationScope[] authorizationScopes new AuthorizationScope[1];authorizationScopes[0] authorizationScope;result.add(new SecurityReference(Authorization, authorizationScopes));return result;}/*** springboot2.6就算配了ant_path_matcher也会和springfox冲突* 解决springboot2.6 和springfox不兼容问题 Failed to start bean ‘ documentationPluginsBootstrapper ‘ ; nested exception…**/Beanpublic static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {return new BeanPostProcessor() {Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {customizeSpringfoxHandlerMappings(getHandlerMappings(bean));}return bean;}private T extends RequestMappingInfoHandlerMapping void customizeSpringfoxHandlerMappings(ListT mappings) {ListT copy mappings.stream().filter(mapping - mapping.getPatternParser() null).collect(Collectors.toList());mappings.clear();mappings.addAll(copy);}SuppressWarnings(unchecked)private ListRequestMappingInfoHandlerMapping getHandlerMappings(Object bean) {try {Field field ReflectionUtils.findField(bean.getClass(), handlerMappings);field.setAccessible(true);return (ListRequestMappingInfoHandlerMapping) field.get(bean);} catch (IllegalArgumentException | IllegalAccessException e) {throw new IllegalStateException(e);}}};} }上面配置中有个接口 public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor()springboot2.6以上版本需要配置中的这个Bean很重要务必加上 认证与授权流程演示 运行项目访问API Swagger3以上的版本访问的地址是http://localhost:8080/swagger-ui/index.html 未登录时访问接口 登录后访问接口 进行登录操作登录帐号test 123456 点击Authorize按钮在弹框中输入登录接口中获取到的token信息 加上接口的注解与表中的数据对应 继续访问 由于test帐号并没有设置任何权限所以他无法访问具有pms:brand:read权限的获取品牌列表接口。 改用其他有权限的帐号登录 改用admin 123456登录后访问点击Authorize按钮打开弹框,点击logout登出后再重新输入新token 可以看到有数据了 总结 上面的案例是在某个接口判断的权限但这个不能动态配置和校验。最好的方式是根据访问的url进行权限校验是最好的这样就不需要在各个接口加注解了。此方式会单独写个教程进行讲解 源码 链接: 整合SpringSecurity和JWT实现认证和授权
http://www.zqtcl.cn/news/691321/

相关文章:

  • 乌海学校网站建设wordpress默认主题下载
  • 海兴县做网站如何选网站建设公司
  • asp网站设为首页代码孝仙洪高速公路建设指挥部网站
  • 浦东新区网站开发人才网站建设策划书
  • 网站做flash好不好免费微信公众号素材网
  • 开发网站嵌入广告汕头电商网站建设
  • 电脑做科目一网站购物网站怎么创建
  • c2c网站建设公司wordpress被公众号干掉
  • wordpress托管建站网站页面布局和样式设计
  • 建站平台江苏省建设监理协会网站
  • 安徽网站开发培训价格百度seo排名公司
  • 青海网站建设费用oa系统和erp系统区别
  • 个人做网站的注意事项网站开发工程师6
  • 镇江百度网站建设北京网站开发价格
  • 大岭山镇仿做网站推广计划表格
  • 网站备案地址不是我的地址怎么办建设银行网站查询业务收费吗
  • 电商网站设计内容网站编辑及seo招聘
  • 用什么网站开发浙江省住房和建设厅网站
  • 站长工具seo优化建议微信小程序线上商城怎么申请
  • 建筑网站开发设计做网站的公司msgg
  • 设计师个人网站模板网站的尾页要怎么做
  • 营销型网站建设风格设定包括哪些方面wordpress企业魔板
  • 怎样做淘客网站做绿色产品的网站
  • 关于网站建设的通知wordpress点注册后一直不出来
  • 科技公司网站设计方案开发公司绩效考核
  • 深圳网站建设推进旗县政务网站建设工作方案
  • 南宁 网站建设网站集约建设
  • 做网站编辑好吗吉林省四平市
  • 石家庄网站制作最新军事新闻最新消息视频
  • 高端品牌网站设计企业网站建设wordpress文章前阅读