Java SpringSecurity+JWT实现登录认证

网友投稿 312 2022-07-25


目录整合步骤实现原理目录结构做了哪些变化

前言:

学习过我的mall项目的应该知道,mall-admin模块是使用SpringSecurity+JWT来实现登录认证的,而mall-portal模块是使用的SpringSecurity基于Session的默认机制来实现登陆认证的。很多小伙伴都找不到mall-portal的登录接口,最近我把这两个模块的登录认证给统一了,都使用SpringSecurity+JWT的形式实现。主要是通过把登录认证的通用逻辑抽取到了mall-security模块来实现的,下面我们讲讲如何使用mall-security模块来实现登录认证,仅需四步即可。

整合步骤

这里我们以mall-portal改造为例来说说如何实现。

第一步,给需要登录认证的模块添加mall-security依赖:

com.macro.mall

mall-security

第二步,添加MallSecurityConfig配置类,继承mall-security中的SecurityConfig配置,并且配置一个UserDetailsService接口的实现类,用于获取登录用户详情:

/**

* mall-security模块相关配置

* Created by macro on 2019/11/5.

*/

@Configuration

@EnableWebSecurity

@EnableGlobalMethodSecurity(prePostEnabled=true)

publicclass MallSecurityConfig extends SecurityConfig {

@Autowired

private UmsMemberService memberService;

@Bean

public UserDetailsService userDetailsService() {

//获取登录用户信息

return username -> memberService.loadUserByUsername(username);

}

}

第三步,在application.yml中配置下不需要安全保护的资源路径:

secure:

ignored:

urls:#安全路径白名单

-/swagger-ui.html

-/swagger-resources/**

-/swagger/**

-/**/v2/api-docs

-/**/*.js

-/**/*.css

-/**/*.png

-/**/*.ico

-/webjars/springfox-swagger-ui/**

-/druid/**

-/actuator/**

-/sso/**

-/home/**

第四步,在UmsMemberController中实现登录和刷新token的接口:

/**

* 会员登录注册管理Controller

* Created by macro on 2018/8/3.

*/

@Controller

@Api(tags = "UmsMemberController", description = "会员登录注册管理")

@RequestMapping("/sso")

publicclass UmsMemberController {

@Value("${jwt.tokenHeader}")

private String tokenHeader;

@Value("${jwt.tokenHead}")

private String tokenHead;

@Autowired

private UmsMemberService memberService;

@ApiOperation("会员登录")

@RequestMapping(value = "/login", method = RequestMethod.POST)

@ResponseBody

public CommonResult login(@RequestParam String username,

@RequestParam String password) {

String token = memberService.login(username, password);

if (token == null) {

return CommonResult.validateFailed("用户名或密码错误");

}

Map tokenMap = new HashMap<>();

tokenMap.put("token", token);

tokenMap.put("tokenHead", tokenHead);

return CommonResult.success(tokenMap);

}

@ApiOperation(value = "刷新token")

@RequestMapping(value = "/refreshToken", method = RequestMethod.GET)

@ResponseBody

public CommonResult refreshToken(HttpServletRequest request) {

String token = request.getHeader(tokenHeader);

String refreshToken = memberService.refreshToken(token);

if (refreshToken == null) {

return CommonResult.failed("token已经过期!");

}

Map tokenMap = new HashMap<>();

tokenMap.put("token", refreshToken);

tokenMap.put("tokenHead", tokenHead);

return CommonResult.success(tokenMap);

}

}

实现原理

将SpringSecurity+JWT的代码封装成通用模块后,就可以方便其他需要登录认证的模块来使用,下面我们来看看它是如何实现的,首先我们看下mall-security的目录结构。

目录结构

mall-security

├── component

| ├── JwtAuthenticationTokenFilter -- JWT登录授权过滤器

| ├── RestAuthenticationEntryPoint -- 自定义返回结果:未登录或登录过期

| └── RestfulAccessDeniedHandler -- 自定义返回结果:没有权限访问时

├── config

| ├── IgnoreUrlsConfig -- 用于配置不需要安全保护的资源路径

| └── SecurityConfig -- SpringSecurity通用配置

└── util

└── JwtTokenUtil -- JWT的token处理工具类

做了哪些变化

其实我也就添加了两个类,一个IgnoreUrlsConfig,用于从application.yml中获取不需要安全保护的资源路径。一个SecurityConfig提取了一些SpringSecurity的通用配置。

IgnoreUrlsConfig中的代码:

/**

* 用于配置不需要保护的资源路径

* Created by macro on 2018/11/5.

*/

@Getter

@Setter

@ConfigurationProperties(prefix = "secure.ignored")

publicclass IgnoreUrlsConfig {

private List urls = new ArrayList<>();

}

SecurityConfig中的代码:

/**

* 对SpringSecurity的配置的扩展,支持自定义白名单资源路径和查询用户逻辑

* Created by macro on 2019/11/5.

*/

publicclass SecurityConfig extends WebSecurityConfigurerAdapter {

@Override

protected void configure(HttpSecurity httpSecurity) throws Exception {

ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry = httpSecurity

.authorizeRequests();

//不需要保护的资源路径允许访问

for (String url : ignoreUrlsConfig().getUrls()) {

registry.antMatchers(url).permitAll();

}

//允许跨域请求的OPTIONS请求

registry.antMatchers(HttpMethod.OPTIONS)

.permitAll();

// 任何请求需要身份认证

registry.and()

.authorizeRequests()

.anyRequest()

.authenticated()

// 关闭跨站请求防护及不使用session

.and()

.csrf()

.disable()

.sessionManagement()

.sessionCreationPolicy(SessionCreationPolicy.STATELESS)

// 自定义权限拒绝处理类

.and()

.exceptionHandling()

.accessDeniedHandler(restfulAccessDeniedHandler())

.authenticationEntryPoint(restAuthenticationEntryPoint())

// 自定义权限拦截器JWT过滤器

.and()

.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);

}

@Override

protected void configure(AuthenticationManagerBuilder auth) throws Exception {

auth.userDetailsService(userDetailsService())

.passwordEncoder(passwordEncoder());

}

@Bean

public PasswordEncoder passwordEncoder() {

returnnew BCryptPasswordEncoder();

}

@Bean

public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() {

returnnew JwtAuthenticationTokenFilter();

}

@Bean

@Override

public AuthenticationManager authenticationManagerBean() throws Exception {

returnsuper.authenticationManagerBean();

}

@Bean

public RestfulAccessDeniedHandler restfulAccessDeniedHandler() {

returnnew RestfulAccessDeniedHandler();

}

@Bean

public RestAuthenticationEntryPoint restAuthenticationEntryPoint() {

returnnew RestAuthenticationEntryPoint();

}

@Bean

public IgnoreUrlsConfig ignoreUrlsConfig() {

returnnew IgnoreUrlsConfig();

}

@Bean

public JwtTokenUtil jwtTokenUtil() {

returnnew JwtTokenUtil();

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Spring MVC的完整执行流程和常用组件详解
下一篇:关于Mybatis与JPA的优缺点说明
相关文章

 发表评论

暂时没有评论,来抢沙发吧~