返回顶部
首页 > 资讯 > 精选 >SpringBoot security安全认证登录如何实现
  • 734
分享到

SpringBoot security安全认证登录如何实现

2023-07-05 05:07:47 734人浏览 独家记忆
摘要

本文小编为大家详细介绍“SpringBoot security安全认证登录如何实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“springBoot security安全认证登录如何实现”文章能帮助大家解决疑惑,下面跟

本文小编为大家详细介绍“SpringBoot security安全认证登录如何实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“springBoot security安全认证登录如何实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

一、登录时序图

SpringBoot security安全认证登录如何实现

时序原图

二、配置与代码

1.引入库

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>

2.代码文件

代码如下(示例):

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

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作