本文小编为大家详细介绍“SpringBoot security安全认证登录如何实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“springBoot security安全认证登录如何实现”文章能帮助大家解决疑惑,下面跟
本文小编为大家详细介绍“SpringBoot security安全认证登录如何实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“springBoot security安全认证登录如何实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。
时序原图
pom.xml:
<!-- Spring框架基本的核心工具 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <!-- SpringWEB模块 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> </dependency> <!-- spring security 安全认证 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!--常用工具类 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <!-- JSON工具类 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <!-- 阿里jsON解析器 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> </dependency> <!-- io常用工具类 --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> </dependency> <!-- yml解析器 --> <dependency> <groupId>org.yaml</groupId> <artifactId>snakeyaml</artifactId> </dependency> <!-- Token生成与解析--> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jJwt</artifactId> </dependency> <!-- Jaxb --> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> </dependency> <!-- redis 缓存操作 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-Redis</artifactId> </dependency> <!-- pool 对象池 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <!-- 解析客户端操作系统、浏览器等 --> <dependency> <groupId>eu.bitwalker</groupId> <artifactId>UserAgentUtils</artifactId> </dependency> <!-- servlet包 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </dependency> <dependency> <groupId>org.apache.Httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.2</version> </dependency>
代码如下(示例):
RedisCache.java :spring redis 工具组件类,注入RedisTemplate,封装Redis缓存数据、对象操作。
import java.util.Collection;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;import java.util.concurrent.TimeUnit;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.BoundSetOperations;import org.springframework.data.redis.core.HashOperations;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.ValueOperations;import org.springframework.stereotype.Component;@SuppressWarnings(value = { "unchecked", "rawtypes" })@Componentpublic class RedisCache{ @Autowired public RedisTemplate redisTemplate; public <T> void setCacheObject(final String key, final T value) { redisTemplate.opsForValue().set(key, value); } public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) { redisTemplate.opsForValue().set(key, value, timeout, timeUnit); } public boolean expire(final String key, final long timeout) { return expire(key, timeout, TimeUnit.SECONDS); } public boolean expire(final String key, final long timeout, final TimeUnit unit) { return redisTemplate.expire(key, timeout, unit); } public <T> T getCacheObject(final String key) { ValueOperations<String, T> operation = redisTemplate.opsForValue(); return operation.get(key); } public boolean deleteObject(final String key) { return redisTemplate.delete(key); } public long deleteObject(final Collection collection) { return redisTemplate.delete(collection); } public <T> long setCacheList(final String key, final List<T> dataList) { Long count = redisTemplate.opsForList().rightPushAll(key, dataList); return count == null ? 0 : count; } public <T> List<T> getCacheList(final String key) { return redisTemplate.opsForList().range(key, 0, -1); } public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet) { BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key); Iterator<T> it = dataSet.iterator(); while (it.hasNext()) { setOperation.add(it.next()); } return setOperation; } public <T> Set<T> getCacheSet(final String key) { return redisTemplate.opsForSet().members(key); } public <T> void setCacheMap(final String key, final Map<String, T> dataMap) { if (dataMap != null) { redisTemplate.opsForHash().putAll(key, dataMap); } } public <T> Map<String, T> getCacheMap(final String key) { return redisTemplate.opsForHash().entries(key); } public <T> void setCacheMapValue(final String key, final String hKey, final T value) { redisTemplate.opsForHash().put(key, hKey, value); } public <T> T getCacheMapValue(final String key, final String hKey) { HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash(); return opsForHash.get(key, hKey); } public void delCacheMapValue(final String key, final String hkey) { HashOperations hashOperations = redisTemplate.opsForHash(); hashOperations.delete(key, hkey); } public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) { return redisTemplate.opsForHash().multiGet(key, hKeys); } public Collection<String> keys(final String pattern) { return redisTemplate.keys(pattern); }}
RedisConfig:redis配置类。
import org.springframework.cache.annotation.CachinGConfigurerSupport;import org.springframework.cache.annotation.EnableCaching;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.script.DefaultRedisScript;import org.springframework.data.redis.serializer.StringRedisSerializer;import com.fasterxml.jackson.annotation.JsonAutoDetect;import com.fasterxml.jackson.annotation.JsonTypeInfo;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;@Configuration@EnableCachingpublic class RedisConfig extends CachingConfigurerSupport{ @Bean @SuppressWarnings(value = { "unchecked", "rawtypes" }) public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<Object, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class); ObjectMapper mapper = new ObjectMapper(); mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); serializer.setObjectMapper(mapper); // 使用StringRedisSerializer来序列化和反序列化redis的key值 template.seTKEySerializer(new StringRedisSerializer()); template.setValueSerializer(serializer); // Hash的key也采用StringRedisSerializer的序列化方式 template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(serializer); template.afterPropertiesSet(); return template; }}
SecurityUtils:安全服务工具类。
import com.ems.mgr.common.constant.httpstatus;import com.ems.mgr.common.exception.ServiceException;import org.springframework.security.core.Authentication;import org.springframework.security.core.context.SecurityContextHolder;import org.springframework.security.crypto.bcrypt.BCryptPassWordEncoder;import com.ems.mgr.common.core.domain.model.LoginUser;public class SecurityUtils{ public static Long getUserId() { try { return getLoginUser().getUserId(); } catch (Exception e) { throw new ServiceException("获取用户ID异常", HttpStatus.UNAUTHORIZED); } } public static Long getDeptId() { try { return getLoginUser().getDeptId(); } catch (Exception e) { throw new ServiceException("获取部门ID异常", HttpStatus.UNAUTHORIZED); } } public static String getUsername() { try { return getLoginUser().getUsername(); } catch (Exception e) { throw new ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED); } } public static LoginUser getLoginUser() { try { return (LoginUser) getAuthentication().getPrincipal(); } catch (Exception e) { throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED); } } public static Authentication getAuthentication() { return SecurityContextHolder.getContext().getAuthentication(); } public static String encryptPassword(String password) { BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); return passwordEncoder.encode(password); } public static boolean matchesPassword(String rawPassword, String encodedPassword) { BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); return passwordEncoder.matches(rawPassword, encodedPassword); } public static boolean isAdmin(Long userId) { return userId != null && 1L == userId; }}
SecurityConfig:spring security配置。
import com.ems.mgr.framework.security.filter.JwtAuthenticationTokenFilter;import com.ems.mgr.framework.security.handle.AuthenticationEntryPointImpl;import com.ems.mgr.framework.security.handle.LoGoutSuccesshandlerImpl;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.http.HttpMethod;import org.springframework.security.authentication.AuthenticationManager;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.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.web.authentication.UsernamePasswordAuthenticationFilter;import org.springframework.security.web.authentication.logout.LogoutFilter;import org.springframework.web.filter.CorsFilter;@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)public class SecurityConfig extends WebSecurityConfigurerAdapter{ @Autowired private UserDetailsService userDetailsService; @Autowired private AuthenticationEntryPointImpl unauthorizedHandler; @Autowired private LogoutSuccessHandlerImpl logoutSuccessHandler; @Autowired private JwtAuthenticationTokenFilter authenticationTokenFilter; @Autowired private CorsFilter corsFilter; @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity // CSRF禁用,因为不使用session .csrf().disable() // 认证失败处理类 .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() // 基于token,所以不需要session .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() // 过滤请求 .authorizeRequests() // 对于登录login 验证码captchaImage 允许匿名访问 .antMatchers("/ems/login", "/ems/captchaImage","/ems/login/sms","/ems/robot**").anonymous() .antMatchers("/tool/gen**").anonymous() .antMatchers("/message/sendOne").anonymous() .antMatchers( HttpMethod.GET, "/", "*.html", "*.CSS", "*.js", "/profileapi-docs").anonymous() .antMatchers("/druid @Bean public BCryptPasswordEncoder bCryptPasswordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //设置DaoAuthenticationProvider类PasswordEncoder passwordEncoder auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder()); }}
spring security配置类配置token认证过滤器(JwtAuthenticationTokenFilter)、
认证失败处理类(AuthenticationEntryPointImpl)、退出处理类(LogoutSuccessHandlerImpl)
1-JwtAuthenticationTokenFilter:
package com.ems.mgr.framework.security.filter;import java.io.IOException;import javax.servlet.FilterChain;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;import org.springframework.security.core.context.SecurityContextHolder;import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;import org.springframework.stereotype.Component;import org.springframework.web.filter.OncePerRequestFilter;import com.ems.mgr.common.core.domain.model.LoginUser;import com.ems.mgr.common.utils.SecurityUtils;import com.ems.mgr.common.utils.StringUtils;import com.ems.mgr.framework.web.service.TokenService;@Componentpublic class JwtAuthenticationTokenFilter extends OncePerRequestFilter{ @Autowired private TokenService tokenService; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { LoginUser loginUser = tokenService.getLoginUser(request); if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication())) { tokenService.verifyToken(loginUser); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities()); authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authenticationToken); } chain.doFilter(request, response); }}
2-AuthenticationEntryPointImpl:认证失败处理类 返回未授权
package com.ems.mgr.framework.security.handle;import java.io.IOException;import java.io.Serializable;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.ems.mgr.common.core.domain.ajaxResult;import org.springframework.security.core.AuthenticationException;import org.springframework.security.web.AuthenticationEntryPoint;import org.springframework.stereotype.Component;import com.alibaba.fastjson.JSON;import com.ems.mgr.common.constant.HttpStatus;import com.ems.mgr.common.utils.ServletUtils;import com.ems.mgr.common.utils.StringUtils;@Componentpublic class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable{ private static final long serialVersionUID = -8970718410437077606L; @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException { int code = HttpStatus.UNAUTHORIZED; String msg = StringUtils.fORMat("请求访问:{},认证失败,无法访问系统资源", request.getRequestURI()); ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg))); }}
3-LogoutSuccessHandlerImpl:自定义退出处理类
package com.ems.mgr.framework.security.handle;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.ems.mgr.common.constant.Constants;import com.ems.mgr.common.core.domain.AjaxResult;import com.ems.mgr.framework.manager.factory.AsyncFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Configuration;import org.springframework.security.core.Authentication;import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;import com.alibaba.fastjson.JSON;import com.ems.mgr.common.constant.HttpStatus;import com.ems.mgr.common.core.domain.model.LoginUser;import com.ems.mgr.common.utils.ServletUtils;import com.ems.mgr.common.utils.StringUtils;import com.ems.mgr.framework.manager.AsyncManager;import com.ems.mgr.framework.web.service.TokenService;@Configurationpublic class LogoutSuccessHandlerImpl implements LogoutSuccessHandler{ @Autowired private TokenService tokenService; @Override public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { LoginUser loginUser = tokenService.getLoginUser(request); if (StringUtils.isNotNull(loginUser)) { String userName = loginUser.getUsername(); // 删除用户缓存记录 tokenService.delLoginUser(loginUser.getToken()); // 记录用户退出日志 AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, "退出成功")); } ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(HttpStatus.SUCCESS, "退出成功"))); }}
读到这里,这篇“SpringBoot security安全认证登录如何实现”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网精选频道。
--结束END--
本文标题: SpringBoot security安全认证登录如何实现
本文链接: https://lsjlt.com/news/350009.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0