SpringBoot 整合security 实现自定义Token
2021-06-09 本文已影响0人
猫的树
接上一篇
6.认证相关处理创建
登录成功 DemoAuthenticationSuccessHandler.java
/**
* 用户身份验证通过处理
*/
@Component
@SuppressWarnings("all")
public class DemoAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Autowired
private TokenService tokenService;
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Authentication authentication) throws IOException, ServletException {
// 取得认证用户信息
UserDetailsInfo userInfo = (UserDetailsInfo) authentication.getDetails();
// 设置用户返回信息
UserInfoOutputDto outputDto = new UserInfoOutputDto();
String username = userInfo.getUsername();
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
outputDto.setRole(userInfo.getRole());
outputDto.setLoginTime(dateFormat.format(date));
outputDto.setUserId(userInfo.getUserId());
outputDto.setUserName(userInfo.getUsername());
// 创建Token
userInfo.setIp(ClientIdUtil.getIp(httpServletRequest));
TokenInfo tokenInfo = tokenService.createToken(userInfo);
outputDto.setClientId(tokenInfo.getClientId());
outputDto.setAccessToken(tokenInfo.getAccessToken());
ResultData data = new ResultData(1, "login successful", outputDto);
Gson gson = new Gson();
httpServletResponse.getWriter().write(gson.toJson(data));
}
}
UserInfoOutputDto.java
/**
* 用户登录返回信息
*/
public class UserInfoOutputDto {
private String userId;
private String userName;
private String role;
private String clientId;
private String accessToken;
private String loginTime;
...
登录失败 DemoAuthenticationFailureHandler.java
/**
* 用户身份验证失败处理
*/
@Component
public class DemoAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
AuthenticationException e) throws IOException, ServletException {
PermissionJsonException jsonException = new PermissionJsonException();
if (e instanceof UsernameNotFoundException) {
jsonException.setCode(10001);
jsonException.setMsg("username not exits");
} else if (e instanceof BadCredentialsException) {
jsonException.setCode(10002);
jsonException.setMsg("wrong password ");
} else if (e instanceof DisabledException) {
jsonException.setCode(10003);
jsonException.setMsg("user is disabled");
} else {
jsonException.setCode(10004);
jsonException.setMsg("error");
}
httpServletResponse.setContentType("application/json;charset=UTF-8");
Gson gson = new Gson();
httpServletResponse.getWriter().write(gson.toJson(jsonException));
}
}
账号同时登录处理 DemoExpiredHandler.java
/**
* 账号同时登录处理
*/
@Component
@SuppressWarnings("all")
public class DemoExpiredHandler implements SessionInformationExpiredStrategy {
@Autowired
private TokenService tokenService;
@Override
public void onExpiredSessionDetected(SessionInformationExpiredEvent
sessionInformationExpiredEvent) throws IOException, ServletException {
// 获取登录的token信息
String clientId = sessionInformationExpiredEvent.getRequest().getHeader("clientId");
TokenInfo tokenInfo = tokenService.findByClientId(clientId);
// 设置账户登录信息
ExpiredData expiredData = new ExpiredData();
// 登录ip
expiredData.setIp(tokenInfo.getIp());
SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd HH:mm");
// 登录时间
expiredData.setLoginTime(dateFormat.format(tokenInfo.getUpdateTime()));
Gson gson = new Gson();
sessionInformationExpiredEvent.getResponse().getWriter().write(gson.toJson(expiredData));
}
}
ExpiredData.java
/**
* 重复登录信息
*/
public class ExpiredData {
/**
* 登录ip
*/
private String ip;
/**
* 登录时间
*/
private String loginTime;
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getLoginTime() {
return loginTime;
}
public void setLoginTime(String loginTime) {
this.loginTime = loginTime;
}
}
重点来了
7.Security配置
package com.example.demo.base.config;
import com.example.demo.base.common.DemoAuthenticationFailureHandler;
import com.example.demo.base.common.DemoAuthenticationProvider;
import com.example.demo.base.common.DemoAuthenticationSuccessHandler;
import com.example.demo.base.common.DemoExpiredHandler;
import com.example.demo.base.common.DemoLogoutSuccessHandler;
import com.example.demo.base.filter.SecurityFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
/**
* Security配置
*/
@Configuration
@SuppressWarnings("all")
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private DemoAuthenticationProvider demoAuthenticationProvider;
@Autowired
private DemoAuthenticationFailureHandler failureHandler;
@Autowired
private DemoAuthenticationSuccessHandler successHandler;
@Autowired
private DemoLogoutSuccessHandler logoutSuccessHandler;
@Autowired
private DemoExpiredHandler expiredHandler;
/**
* 验证用户密码
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(demoAuthenticationProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/favicon.ico").permitAll()
// 请求需要身份认证
.anyRequest().authenticated()
// 配置登录页面
.and().formLogin()
.loginPage("/nopermission")
// 登录请求url
.loginProcessingUrl("/login")
// 身份验证成功/失败 处理
.successHandler(successHandler).failureHandler(failureHandler).permitAll()
// 退出登录处理
.and().logout().logoutUrl("/logout")
.logoutSuccessHandler(logoutSuccessHandler)
.deleteCookies("JSESSIONID")
.and().addFilterAt(securityFilter(), FilterSecurityInterceptor.class).exceptionHandling()
// 相同账号的最大用户数
.and().sessionManagement().maximumSessions(1)
.expiredSessionStrategy(expiredHandler);
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/static/**");
}
@Bean
SecurityFilter securityFilter() {
return new SecurityFilter();
// 这个方法才能在拦截器中自动注入查询数据库的对象
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
代码写到这,一个实现Token验证的登录就写好了,下一篇我们可以测试一下是否成功。