赞
踩
https://github.com/typ1805/blog-cloud
Spring Security是一套安全框架,可以基于RBAC(基于角色的权限控制)对用户的访问权限进行控制。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
</dependency>
登录认证授权等主要采用Spring security + JWT,首先配置WebSecurityConfig,Redis配置主要是为了满足需:
package com.blog.config; import com.blog.jwt.JWTAuthenticationEntryPoint; import com.blog.jwt.JWTAuthenticationFilter; import com.blog.jwt.JWTAuthorizationFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.http.HttpMethod; 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.config.http.SessionCreationPolicy; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; /** * @path:com.blog.config.WebSecurityConfig.java * @className:WebSecurityConfig.java * @description:Security配置 * @author:tanyp * @dateTime:2020/11/9 16:31 * @editNote: */ @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired @Qualifier("userDetailsServiceImpl") private UserDetailsService userDetailsService; @Autowired private StringRedisTemplate redisTemplate; @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/login").permitAll() .anyRequest().authenticated() .and() .addFilterBefore(new JWTAuthenticationFilter(authenticationManager(), redisTemplate), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(new JWTAuthorizationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class) .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .exceptionHandling().authenticationEntryPoint(new JWTAuthenticationEntryPoint()); } }
通过用户名去查找用户及拥有的角色和权限
package com.blog.service; import com.blog.domain.AuthUser; import com.blog.common.core.constants.Constants; import com.blog.common.core.constants.JWTConstants; import com.blog.common.core.result.Wrapper; import com.blog.provider.UserProvider; import com.blog.vo.MenuVo; import com.blog.vo.RoleVo; import com.blog.vo.UserVo; import org.apache.dubbo.config.annotation.DubboReference; import org.springframework.beans.BeanUtils; 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 org.springframework.util.StringUtils; import java.util.HashSet; import java.util.List; import java.util.Set; /** * @path:com.blog.service.impl.UserDetailsServiceImpl.java * @className:UserDetailsServiceImpl.java * @description:自定义用户认证和授权 * @author:tanyp * @dateTime:2020/11/9 15:44 * @editNote: */ @Service public class UserDetailsServiceImpl implements UserDetailsService { @DubboReference private UserProvider userProvider; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { Wrapper<UserVo> userInfo = userProvider.findByUsername(username); if (userInfo.getCode() != Constants.SUCCESS) { throw new UsernameNotFoundException("用户:" + username + ",不存在!"); } Set<SimpleGrantedAuthority> grantedAuthorities = new HashSet<>(); UserVo userVo = new UserVo(); BeanUtils.copyProperties(userInfo.getResult(), userVo); Wrapper<List<RoleVo>> roleInfo = userProvider.getRoleByUserId(String.valueOf(userVo.getId())); if (roleInfo.getCode() == Constants.SUCCESS) { List<RoleVo> roleVoList = roleInfo.getResult(); for (RoleVo role : roleVoList) { // 角色必须是ROLE_开头,可以在数据库中设置 SimpleGrantedAuthority grantedAuthority = new SimpleGrantedAuthority(JWTConstants.ROLE_PREFIX + role.getValue()); grantedAuthorities.add(grantedAuthority); // 获取权限 Wrapper<List<MenuVo>> menuInfo = userProvider.getRolePermission(String.valueOf(role.getId())); if (menuInfo.getCode() == Constants.SUCCESS) { List<MenuVo> permissionList = menuInfo.getResult(); for (MenuVo menu : permissionList) { if (!StringUtils.isEmpty(menu.getUrl())) { SimpleGrantedAuthority authority = new SimpleGrantedAuthority(menu.getUrl()); grantedAuthorities.add(authority); } } } } } AuthUser user = new AuthUser(userVo.getUsername(), userVo.getPassword(), grantedAuthorities); user.setId(userVo.getId()); return user; } }
主要对用户进行认证工作,当登录时,获取用户名和密码,通过authenticationManager.authenticate,最终会调用UserDetailsServiceImpl来获取用户信息(在DaoAuthenticationProvider的retrieveUser中),
然后在DaoAuthenticationProvider的additionalAuthenticationChecks中校验密码。
package com.blog.jwt; import com.alibaba.fastjson.JSONObject; import com.blog.domain.AuthUser; import com.blog.common.core.constants.JWTConstants; import com.blog.common.core.result.WrapMapper; import com.nimbusds.jose.JOSEException; import com.nimbusds.jose.JWSVerifier; import com.nimbusds.jose.crypto.MACVerifier; import com.nimbusds.jwt.SignedJWT; import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; import org.springframework.security.authentication.AccountExpiredException; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; import org.springframework.util.StringUtils; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.text.ParseException; import java.util.Date; /** * @path:com.blog.jwt.JWTAuthorizationFilter.java * @className:JWTAuthorizationFilter.java * @description:授权 * @author:tanyp * @dateTime:2020/11/19 13:19 * @editNote: */ @Slf4j public class JWTAuthorizationFilter extends BasicAuthenticationFilter { public JWTAuthorizationFilter(AuthenticationManager authenticationManager) { super(authenticationManager); } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { String token = request.getHeader(JWTConstants.TOKEN_HEADER); if (StringUtils.isEmpty(token) || !token.startsWith(JWTConstants.TOKEN_PREFIX)) { chain.doFilter(request, response); return; } try { Authentication authentication = getAuthentication(token); SecurityContextHolder.getContext().setAuthentication(authentication); onSuccessfulAuthentication(request, response, authentication); chain.doFilter(request, response); } catch (Exception e) { e.printStackTrace(); onUnsuccessfulAuthentication(request, response, new AccountExpiredException(e.getMessage())); } } @Override protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) throws IOException { log.info("=============Token 验证成功================="); } @Override protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException { log.error("================token校验失败======================="); response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setCharacterEncoding("UTF-8"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.getWriter().write(JSONObject.toJSONString(WrapMapper.error(HttpServletResponse.SC_UNAUTHORIZED, failed.getMessage()))); } /** * @methodName:getAuthentication * @description:这里从token中获取用户信息并新建一个token * @author:tanyp * @dateTime:2020/11/19 13:37 * @Params: [tokenHeader] * @Return: org.springframework.security.authentication.UsernamePasswordAuthenticationToken * @editNote: */ private UsernamePasswordAuthenticationToken getAuthentication(String tokenHeader) throws ParseException, JOSEException { String token = tokenHeader.replace(JWTConstants.TOKEN_PREFIX, ""); SignedJWT jwt = SignedJWT.parse(token); JWSVerifier verifier = new MACVerifier(JWTConstants.SECRET); // 校验是否有效 if (!jwt.verify(verifier)) { throw new AccountExpiredException(JWTConstants.TOKEN_INVALID); } // 校验超时 Date expirationTime = jwt.getJWTClaimsSet().getExpirationTime(); if (new Date().after(expirationTime)) { throw new AccountExpiredException(JWTConstants.TOKEN_EXPIRE); } // 获取载体中的数据 Object account = jwt.getJWTClaimsSet().getClaim("payload"); if (account != null) { AuthUser user = JSONObject.parseObject(account.toString(), AuthUser.class); return new UsernamePasswordAuthenticationToken(user.getUsername(), null, user.getAuthorities()); } return null; } }
在JWTAuthenticationFilter中,把权限信息等写入到了redis中。
只要后台权限变动的时候,根据key的规则清除redis数据即可, 然后在gateway中获取不到相应的权限, 那么会要求用户重新登录。
package com.blog.jwt; import com.alibaba.fastjson.JSONObject; import com.blog.common.core.constants.JWTConstants; import com.blog.common.core.constants.RedisConstants; import com.blog.common.core.enums.AuthEnum; import com.blog.common.core.result.WrapMapper; import com.blog.common.core.result.Wrapper; import com.blog.common.core.utils.JWTUtiles; import com.blog.common.core.utils.Md5Utils; import com.blog.domain.AuthUser; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.http.MediaType; import org.springframework.security.authentication.AuthenticationManager; 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.security.web.authentication.UsernamePasswordAuthenticationFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.concurrent.TimeUnit; /** * @path:com.blog.jwt.JWTAuthenticationFilter.java * @className:JWTAuthenticationFilter.java * @description:权限变动重新授权 * @author:tanyp * @dateTime:2020/11/19 13:15 * @editNote: */ @Slf4j public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter { private AuthenticationManager authenticationManager; private StringRedisTemplate redisTemplate; public JWTAuthenticationFilter(AuthenticationManager authenticationManager, StringRedisTemplate redisTemplate) { this.authenticationManager = authenticationManager; this.redisTemplate = redisTemplate; } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { String username = request.getParameter("username"); String password = request.getParameter("password"); return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)); } @SneakyThrows @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { AuthUser user = (AuthUser) authResult.getPrincipal(); // 生成token String payload = JSONObject.toJSONString(user); String jwtToken = JWTUtiles.createToken(payload); // 生成Key, 把权限放入到redis中 String keyPrefix = RedisConstants.TOKEN_KEY_PREFIX + user.getId() + ":"; String keySuffix = Md5Utils.getMD5(jwtToken.getBytes()); String key = keyPrefix + keySuffix; String authKey = key + RedisConstants.AUTH_KEY; redisTemplate.opsForValue().set(key, jwtToken, JWTConstants.EXPIRE_TIME, TimeUnit.MILLISECONDS); redisTemplate.opsForValue().set(authKey, JSONObject.toJSONString(user.getAuthorities()), JWTConstants.EXPIRE_TIME, TimeUnit.SECONDS); response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setCharacterEncoding("UTF-8"); response.getWriter().write(JSONObject.toJSONString(WrapMapper.success().result(jwtToken))); } @Override protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException { log.error("========登录认证失败:", failed); Wrapper result = null; int status = AuthEnum.AUTH_NO_TOKEN.getKey(); if (failed instanceof UsernameNotFoundException) { result = WrapMapper.error(AuthEnum.AUTH_NONEXISTENT.getKey(), AuthEnum.AUTH_NONEXISTENT.getValue()); } else if (failed instanceof BadCredentialsException) { result = WrapMapper.error(AuthEnum.AUTH_NO_TOKEN.getKey(), AuthEnum.AUTH_NO_TOKEN.getValue()); } response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setCharacterEncoding("UTF-8"); response.setStatus(status); response.getWriter().write(JSONObject.toJSONString(result)); } }
注: 主要是生成JWT的token, 并且把权限信息放入redis。
登录直接调用Security框架的login方法即可
格式:
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0IiwicGF5bG9hZCI6IntcImFjY291bnROb25FeHBpcmVkXCI6dHJ1ZSxcImFjY291bnROb25Mb2NrZWRcIjp0cnVlLFwiYXV0aG9yaXRpZXNcIjpbe1wiYXV0aG9yaXR5XCI6XCJcL21zcy11cG1zXC9vcmRlclwvbGlzdFwifSx7XCJhdXRob3JpdHlcIjpcIlwvbXNzLXVwbXNcL29yZGVyXC9kZXRhaWxcIn0se1wiYXV0aG9yaXR5XCI6XCJST0xFX2FkbWluXCJ9XSxcImNyZWRlbnRpYWxzTm9uRXhwaXJlZFwiOnRydWUsXCJlbmFibGVkXCI6dHJ1ZSxcImlkXCI6NDgsXCJwYXNzd29yZFwiOlwiJDJhJDEwJHZtcC56V1duWDNMRnhTczZJMDBpMGV1cmxIUjd5bWNmVVE1SHRYdzcxdzlRSi4ySlVmOFVhXCIsXCJ1c2VybmFtZVwiOlwiYWRtaW5cIn0iLCJleHAiOjE2MDYxMzA4MDd9.Wb-2UkAcVrj4KbQteT6D9RbktXgkPLI-tB5ymMkqsjI
网关的主要作用是对JWT和具体的URL进行校验,校验不通过则返回错误信息,主要通过AuthGlobalFilter来实现。
package com.blog.filter; import com.alibaba.fastjson.JSON; import com.blog.common.core.constants.JWTConstants; import com.blog.common.core.constants.RedisConstants; import com.blog.common.core.enums.AuthEnum; import com.blog.common.core.result.WrapMapper; import com.blog.common.core.utils.JWTUtiles; import com.blog.common.core.utils.Md5Utils; import com.blog.config.ExclusionUrlConfig; import com.blog.vo.Authority; import com.blog.vo.UserVo; import com.nimbusds.jwt.SignedJWT; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import org.springframework.util.AntPathMatcher; import org.springframework.util.StringUtils; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import java.text.ParseException; import java.util.List; /** * @path:com.blog.filter.AuthGlobalFilter.java * @className:AuthGlobalFilter.java * @description:token过滤器 * @author:tanyp * @dateTime:2020/11/10 18:06 * @editNote: */ @Slf4j @Component public class AuthGlobalFilter implements GlobalFilter, Ordered { @Autowired private ExclusionUrlConfig exclusionUrlConfig; AntPathMatcher antPathMatcher = new AntPathMatcher(); @Autowired private StringRedisTemplate redisTemplate; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); String headerToken = request.getHeaders().getFirst(JWTConstants.TOKEN_HEADER); log.info("headerToken:{}", headerToken); // 只要带上了token, 就需要判断Token是否有效 if (!StringUtils.isEmpty(headerToken) && !JWTUtiles.verifierToken(headerToken)) { return getVoidMono(response, AuthEnum.AUTH_NO_TOKEN.getKey(), AuthEnum.AUTH_NO_TOKEN.getValue()); } String path = request.getURI().getPath(); log.info("request path:{}", path); // 判断是否是过滤的路径, 是的话就放行 if (isExclusionUrl(path)) { return chain.filter(exchange); } // 判断请求的URL是否有权限 boolean permission = hasPermission(headerToken, path); if (!permission) { return getVoidMono(response, AuthEnum.AUTH_NO_ACCESS.getKey(), AuthEnum.AUTH_NO_ACCESS.getValue()); } return chain.filter(exchange); } @Override public int getOrder() { return 0; } private Mono<Void> getVoidMono(ServerHttpResponse response, int i, String msg) { response.getHeaders().setContentType(MediaType.APPLICATION_JSON); response.setStatusCode(HttpStatus.OK); byte[] bits = JSON.toJSONString(WrapMapper.error(i, msg)).getBytes(); DataBuffer buffer = response.bufferFactory().wrap(bits); return response.writeWith(Mono.just(buffer)); } private boolean isExclusionUrl(String path) { List<String> exclusions = exclusionUrlConfig.getUrl(); if (exclusions.size() == 0) { return false; } return exclusions.stream().anyMatch(action -> antPathMatcher.match(action, path)); } /** * @methodName:hasPermission * @description:判断请求的URL是否有权限 * @author:tanyp * @dateTime:2020/11/24 9:38 * @Params: [headerToken, path] * @Return: boolean * @editNote: */ private boolean hasPermission(String headerToken, String path) { try { if (StringUtils.isEmpty(headerToken)) { return false; } SignedJWT jwt = JWTUtiles.getSignedJWT(headerToken); Object payload = jwt.getJWTClaimsSet().getClaim("payload"); UserVo user = JSON.parseObject(payload.toString(), UserVo.class); // 生成Key, 把权限放入到redis中 String keyPrefix = RedisConstants.TOKEN_KEY_PREFIX + user.getId() + ":"; String token = headerToken.replace(JWTConstants.TOKEN_PREFIX, ""); String keySuffix = Md5Utils.getMD5(token.getBytes()); String key = keyPrefix + keySuffix; String authKey = key + RedisConstants.AUTH_KEY; String authStr = redisTemplate.opsForValue().get(authKey); if (StringUtils.isEmpty(authStr)) { return false; } List<Authority> authorities = JSON.parseArray(authStr, Authority.class); return authorities.stream().anyMatch(authority -> antPathMatcher.match(authority.getAuthority(), path)); } catch (ParseException e) { e.printStackTrace(); } return false; } }
package com.blog.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.util.List; /** * @path:com.blog.config.ExclusionUrlConfig.java * @className:ExclusionUrlConfig.java * @description:白名单配置 * @author:tanyp * @dateTime:2020/11/19 14:01 * @editNote: */ @Data @Component @ConfigurationProperties(prefix = "exclusion") public class ExclusionUrlConfig { private List<String> url; }
配置信息
# 配置白名单路径
exclusion:
url:
- /auth/checkUser
- /auth/login
package com.blog.common.core.utils; import com.blog.common.core.constants.JWTConstants; import com.nimbusds.jose.JOSEException; import com.nimbusds.jose.JWSAlgorithm; import com.nimbusds.jose.JWSHeader; import com.nimbusds.jose.JWSVerifier; import com.nimbusds.jose.crypto.MACSigner; import com.nimbusds.jose.crypto.MACVerifier; import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; import lombok.extern.slf4j.Slf4j; import java.text.ParseException; import java.util.Date; /** * @path:com.blog.common.core.utils.JWTUtiles.java * @className:JWTUtiles.java * @description:JWT工具类 * @author:tanyp * @dateTime:2020/11/24 9:32 * @editNote: */ @Slf4j public class JWTUtiles { /** * @methodName:createToken * @description:创建token * @author:tanyp * @dateTime:2020/11/24 10:20 * @Params: [user] * @Return: java.lang.String * @editNote: */ public static String createToken(String payload) throws JOSEException { // 创建密钥 MACSigner macSigner = new MACSigner(JWTConstants.SECRET); // payload JWTClaimsSet claimsSet = new JWTClaimsSet.Builder() .subject("subject") .claim("payload", payload) .expirationTime(new Date(System.currentTimeMillis() + JWTConstants.EXPIRE_TIME)) .build(); JWSHeader jwsHeader = new JWSHeader(JWSAlgorithm.HS256); // 创建签名的JWT SignedJWT signedJWT = new SignedJWT(jwsHeader, claimsSet); signedJWT.sign(macSigner); // 生成token String jwtToken = signedJWT.serialize(); return jwtToken; } /** * @methodName:verifierToken * @description:验证token * @author:tanyp * @dateTime:2020/11/24 9:35 * @Params: [headerToken] * @Return: boolean * @editNote: */ public static boolean verifierToken(String headerToken) { try { SignedJWT jwt = getSignedJWT(headerToken); JWSVerifier verifier = new MACVerifier(JWTConstants.SECRET); // 校验是否有效 if (!jwt.verify(verifier)) { log.error("token不合法,检测不过关"); return false; } // 校验超时 Date expirationTime = jwt.getJWTClaimsSet().getExpirationTime(); if (new Date().after(expirationTime)) { log.error("token已经过期"); return false; } // 获取载体中的数据 return true; } catch (ParseException | JOSEException e) { log.error("token校验出错", e); } return false; } public static SignedJWT getSignedJWT(String headerToken) throws ParseException { String token = headerToken.replace(JWTConstants.TOKEN_PREFIX, ""); log.info("token is {}", token); return SignedJWT.parse(token); } }
package com.blog.common.core.utils; import java.io.UnsupportedEncodingException; /** * @path:com.blog.common.core.utils.Md5Utils.java * @className:Md5Utils.java * @description:MD5加密 * @author:tanyp * @dateTime:2020/11/9 15:31 * @editNote: */ public class Md5Utils { private static final int HEX_VALUE_COUNT = 16; public static String getMD5(byte[] bytes) { char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; char[] str = new char[16 * 2]; try { java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); md.update(bytes); byte[] tmp = md.digest(); int k = 0; for (int i = 0; i < HEX_VALUE_COUNT; i++) { byte byte0 = tmp[i]; str[k++] = hexDigits[byte0 >>> 4 & 0xf]; str[k++] = hexDigits[byte0 & 0xf]; } } catch (Exception e) { e.printStackTrace(); } return new String(str); } public static String getMD5(String value, String encode) { String result = ""; try { result = getMD5(value.getBytes(encode)); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return result; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。