Средства фильтрации интерфейса Разрешения для определенного интерфейса или функций,систему, установив определенные правила из Разрешения,Разрешено только через Аутентификацию личностии иметь соответствующие Разрешенияиз Доступ и операции пользователя или приложения。Эта технология может эффективно защититьсистема Безопасность ресурсов и данных,Предотвратите выполнение вредоносных операций или несанкционированного доступа неавторизованными пользователями или программами. Обычно,Фильтрацию разрешения интерфейса необходимо использовать в сочетании с другими мерами безопасности.,Например, шифрование, аутентификация личности, аудит и т. д.,Для достижения комплексного защитного эффекта.
Прежде чем реализовывать фильтрацию разрешений пользовательского интерфейса, необходимо сначала импортировать зависимости, в первую очередь Родительская зависимость SpringBoot。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.0</version>
</parent>
Далее идет веб-зависимость Spring Boot, которая обеспечивает самую базовую поддержку интерфейса.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
При реализации входа в систему вам необходимо разработать токен и интегрировать Redis, поэтому вам необходимо добавить следующие зависимости.
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.21.3</version>
</dependency>
Наконец, существует зависимость Spring Security, которая используется для реализации контроля разрешений.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Spring Boot 3.1 версия, соответствующая Spring Security Зависит от 6.1.0 Версия,Заброшенный WebSecurityConfigurerAdapter классы, содержимое конфигурации и Spring Security 5 Существуют очевидные различия, а зависимости версий показаны на рисунке ниже.
Для реализации пользовательского интерфейса Разрешения фильтрации,Прежде всегоОпределить подсказку Авторизоватьсяинтерфейс,Используется для возврата пользовательских данных при перехвате,Как показано ниже.
Попросите учащихся создать новый контроллер. SecurityController
,определите это /zwz/common/needLogin
Интерфейс, код следующий.
@RestController
@RequestMapping("/zwz/common")
@Api(tags = "Интерфейс")
@Транзакционный
общественный класс SecurityController {
@RequestMapping(value = "/needLogin", method = RequestMethod.GET)
@ApiOperation(value = «Данные не возвращены»)
public Result<Object> needLogin(){
return ResultUtil.error(401, "Авторизоваться Неверный"); }
}
Многие студенты задаются вопросом, где находится интерфейс входа в проект Spring Security и как реализовать функцию входа в систему.
существовать Spring Security середина,насВам нужно только настроить интерфейс входа в систему, обратные вызовы при успешном/неуспешном входе в систему, фильтры и т. д.Вот и все,Разработчикам не нужно внимание наавторизоваться конкретной реализации.
Попросите учащихся создать новую AuthenticationSuccessHandler
класс, унаследованный от Spring Security из SavedRequestAwareAuthenticationSuccessHandler
добрый ,Метод успешного перезвона пользователю Авторизоваться,。
@ApiOperation(value = "Войти успешный обратный вызов")
@Slf4j
@Component
public class AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
}
Попросите учащихся сначала переписать AuthenticationSuccessHandler
добрыйсерединаиз onAuthenticationSuccess
метод,这个метод用于выполнитьВойти успешный обратный вызов。
@Override
@ApiOperation(value = "Войти успешный обратный вызов")
@SystemLog(about = "Авторизоватьсясистема", type = LogType.LOGIN)
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication ac) throws IOException, ServletException {
}
существоватьвыполнить Войти успешный обратный вызовизстарт,Сначала необходимо определить, проверил ли пользователь автоматическую Авторизацию.,Код для проверки авторизации выглядит следующим образом.
String saveLogin = request.getParameter(ZwzLoginProperties.SAVE_LOGIN_PRE);
Boolean saveLoginFlag = false;
if(!ZwzNullUtils.isNull(saveLogin) && Objects.equals(saveLogin,"true")){
saveLoginFlag = true;
}
Таким образом, пользователю стоит ли сохранять Авторизоватьсяиз Сохранить логотипсуществовать saveLoginFlag
переменная для последующего сохранения Token использовать.
После успешной авторизации пользователя,Необходимо загрузить пользователя из меню,в это времяУчетная запись пользователя и меню должны быть сохранены в кеше.。
Пользователю не нужно авторизоваться второй раз.,Вот и всеБыстрое получение данных меню из кэша,Ускорить загрузку пользовательского меню,Уменьшите нагрузку на чтение базы данных。
Сначала определите TokenUser
добрый,Используется для хранения временной информации о пользователе (аккаунт, меню Разрешения),Код следующий.
@ApiOperation(value = "Временный пользователь добрый")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TokenUser implements Serializable{
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "имя пользователя")
private String username;
@ApiModelProperty(value = "иметьизменю Разрешения") private List<String> permissions;
@ApiModelProperty(value = "Это автоматически?Авторизоваться") private Boolean saveLogin;
}
Тогда продолжайте существовать onAuthenticationSuccess
Реализуйте метод извлечения меню.
List<String> permissionsList = new ArrayList<>();
List<GrantedAuthority> authorities = (List<GrantedAuthority>) ((UserDetails)ac.getPrincipal()).getAuthorities();
for(GrantedAuthority g : authorities){
permissionsList.add(g.getAuthority());
}
String username = ((UserDetails)ac.getPrincipal()).getUsername();
TokenUser user = new TokenUser(username, permissionsList, saveLoginFlag);
Приведенный выше код вытащит указанного пользователя из меню «Разрешения» и сохранит его в TokenUser
Временный пользователь добрый для последующих звонков.
Одноточечная аутентификация (SSO) — это технология или протокол аутентификации, который позволяет пользователям использовать одну и ту же группу в нескольких приложениях. Учетные данные (такие как имя пользователя и пароль): вам нужно пройти аутентификацию только один раз, чтобы получить доступ ко всем приложениям, что обеспечивает совместное использование информации аутентификации личности между различными приложениями. Эта технология может повысить удобство пользователя, избежать дублирования и снизить нагрузку на управление паролями. Она также может повысить безопасность и снизить риск утечки паролей и атак.
Для общей системы управления поддерживается единая точка «Авторизоваться».
С точки зрения непрофессионала,Единый вход означает, что одна учетная запись позволяет входить в систему только из одного места.,компьютер A При входе в систему, если вы входите в свой компьютер Б, в это время компьютер A будет "вершина" офлайн.
Тогда продолжайте существовать onAuthenticationSuccess
Реализуйте единый вход в метод.
public static final String HTTP_TOKEN_PRE = "ZWZ_TOKEN_PRE:";
public static final String USER_TOKEN_PRE = "ZWZ_USER_TOKEN:";
String oldToken = redisTemplate.opsForValue().get(ZwzLoginProperties.USER_TOKEN_PRE + username);
if(StrUtil.isNotBlank(oldToken)){
redisTemplate.delete(ZwzLoginProperties.HTTP_TOKEN_PRE + oldToken);
}
Если старый из Token Если у вас еще есть существование, просто оставьте старое Token Удалите, чтобы реализовать функцию единого входа.
наконец,Сохранение пользовательских данных для Redis в, будет Token Вернитесь во внешний интерфейс и сохраните его в Cookie , можно использовать переднюю часть Token Авторизуйтесь и получите доступ к системе без входа в систему.
сначала это Token создано, может быть использовано UUID добрый Вспомогательное поколение,Код следующий.
String token = UUID.randomUUID().toString();
инъекция Redis инструментдобрый,Код следующий.
import org.springframework.data.redis.core.StringRedisTemplate;
@Autowired
private StringRedisTemplate redisTemplate;
Тогда согласно 3.1 Шаг за шагом Стоит ли сохранять
В результате выполняется постоянная обработка, и учащиеся могут настроить Token из префикса USER_TOKEN_PRE
。
public static final String HTTP_TOKEN_PRE = "ZWZ_TOKEN_PRE:";
public static final String USER_TOKEN_PRE = "ZWZ_USER_TOKEN:";
if(saveLoginFlag){
redisTemplate.opsForValue().set(ZwzLoginProperties.USER_TOKEN_PRE + username, token, 30, TimeUnit.DAYS);
redisTemplate.opsForValue().set(ZwzLoginProperties.HTTP_TOKEN_PRE + token, JSON.toJSONString(user), 30, TimeUnit.DAYS);
}else{
redisTemplate.opsForValue().set(ZwzLoginProperties.USER_TOKEN_PRE + username, token, 60, TimeUnit.MINUTES);
redisTemplate.opsForValue().set(ZwzLoginProperties.HTTP_TOKEN_PRE + token, JSON.toJSONString(user), 60, TimeUnit.MINUTES);
}
ResponseUtil.out(response, ResponseUtil.resultMap(true, 200,"Авторизоватьсяуспех", token));
когда пользовательСохранить логин отмечен,системадержать Token 30 дней, то есть пользователи могут существовать в будущем 30 В течение нескольких дней вам не потребуется входить в систему.
Если пользовательСнимите флажок Сохранить логин.,системадержать Token 60 минут, что пользователь сможет существовать в будущем 1 В течение нескольких часов вам не потребуется входить в систему.
Полный код выглядит следующим образом.
@ApiOperation(value = "Войти успешный обратный вызов")
@Slf4j
@Component
public class AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
@Autowired
private ZwzLoginProperties tokenProperties;
@Autowired
private StringRedisTemplate redisTemplate;
private static final boolean RESPONSE_SUCCESS_FLAG = true;
private static final int RESPONSE_SUCCESS_CODE = 200;
private static final String TOKEN_REPLACE_STR_FRONT = "-";
private static final String TOKEN_REPLACE_STR_BACK = "";
@Override
@ApiOperation(value = "Войти успешный обратный вызов")
@SystemLog(about = "Авторизоватьсясистема", type = LogType.LOGIN)
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication ac) throws IOException, ServletException {
String saveLogin = request.getParameter(ZwzLoginProperties.SAVE_LOGIN_PRE);
Boolean saveLoginFlag = false;
if(!ZwzNullUtils.isNull(saveLogin) && Objects.equals(saveLogin,"true")){
saveLoginFlag = true;
}
List<String> permissionsList = new ArrayList<>();
List<GrantedAuthority> authorities = (List<GrantedAuthority>) ((UserDetails)ac.getPrincipal()).getAuthorities();
for(GrantedAuthority g : authorities){
permissionsList.add(g.getAuthority());
}
String token = UUID.randomUUID().toString().replace(TOKEN_REPLACE_STR_FRONT, TOKEN_REPLACE_STR_BACK);
String username = ((UserDetails)ac.getPrincipal()).getUsername();
TokenUser user = new TokenUser(username, permissionsList, saveLoginFlag);
// Определите, следует ли сохранять меню Разрешения
if(!tokenProperties.getSaveRoleFlag()){
user.setPermissions(null);
}
// 单点Авторизоватьсясуждение if(tokenProperties.getSsoFlag()){
String oldToken = redisTemplate.opsForValue().get(ZwzLoginProperties.USER_TOKEN_PRE + username);
if(StrUtil.isNotBlank(oldToken)){
redisTemplate.delete(ZwzLoginProperties.HTTP_TOKEN_PRE + oldToken);
}
}
if(saveLoginFlag){
redisTemplate.opsForValue().set(ZwzLoginProperties.USER_TOKEN_PRE + username, token, tokenProperties.getUserSaveLoginTokenDays(), TimeUnit.DAYS);
redisTemplate.opsForValue().set(ZwzLoginProperties.HTTP_TOKEN_PRE + token, JSON.toJSONString(user), tokenProperties.getUserSaveLoginTokenDays(), TimeUnit.DAYS);
}else{
redisTemplate.opsForValue().set(ZwzLoginProperties.USER_TOKEN_PRE + username, token, tokenProperties.getUserTokenInvalidDays(), TimeUnit.MINUTES);
redisTemplate.opsForValue().set(ZwzLoginProperties.HTTP_TOKEN_PRE + token, JSON.toJSONString(user), tokenProperties.getUserTokenInvalidDays(), TimeUnit.MINUTES);
}
ResponseUtil.out(response, ResponseUtil.resultMap(RESPONSE_SUCCESS_FLAG,RESPONSE_SUCCESS_CODE,"Авторизоваться 성공", token));
}
}
Попросите учащихся создать новую AuthenticationFailHandler
класс, унаследованный от Spring Security из SimpleUrlAuthenticationFailureHandler
добрый , используется для обратного вызова при ошибке входа пользователя из метода,.
@ApiOperation(value = "Обратный вызов при ошибке входа")
@Slf4j
@Component
public class AuthenticationFailHandler extends SimpleUrlAuthenticationFailureHandler {
}
Попросите учащихся сначала переписать AuthenticationFailHandler
добрыйсерединаиз onAuthenticationFailure
метод,这个метод用于выполнитьОбратный вызов при ошибке входа。
@Override
@ApiOperation(value = "Обратный вызов при ошибке входа")
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) {
}
существоватьвыполнить Обратный вызов при ошибке входиз Начните с определения того, ввел ли пользователь неправильный пароль.
К ошибкам с паролями относятся:
if (exception instanceof BadCredentialsException || exception instanceof UsernameNotFoundException) {
recordLoginTime(request.getParameter("username:"));
String failTimesStr = stringRedisTemplate.opsForValue().get("LOGIN_FAIL_TIMES_PRE:" + request.getParameter("username:"));
// Время ошибок
int userFailTimes = 0;
if(!ZwzNullUtils.isNull(failTimesStr)){
userFailTimes = Integer.parseInt(failTimesStr);
}
int restLoginTime = 10 - userFailTimes;
if(restLoginTime < 5 && restLoginTime > 0){
ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"Пароль учетной записи неверен, вы все равно можете попробовать Авторизоваться" + restLoginTime + «Второсортный»);
} else if(restLoginTime < 1) {
ResponseUtil.out(response, ResponseUtil.resultMap(false,500, «Повторная попытка превышает лимит, пожалуйста» + 10 + "После разделения Авторизоваться")); } else {
ResponseUtil.out(response, ResponseUtil.resultMap(false,500, «Пароль учетной записи неверен»);
}
}
Настройка по умолчанию 10 Второсортный Авторизоваться试错Второсортный数,Если оно превышает лимитбудетвременный запрет Авторизоваться。
в recordLoginTime
метод用于查询Авторизоватьсянеудачаиз Второсортный数,Код следующий.
@ApiOperation(value = "Количество неудачных запросов на Авторизацию")
public boolean recordLoginTime(String username) {
String loginFailTimeStr = stringRedisTemplate.opsForValue().get(LOGIN_FAIL_TIMES_PRE + username);
int loginFailTime = 0;
// Количество ошибок
if(!ZwzNullUtils.isNull(loginFailTimeStr)){
loginFailTime = Integer.parseInt(loginFailTimeStr) + 1;
}
stringRedisTemplate.opsForValue().set("LOGIN_FAIL_TIMES_PRE:" + username, loginFailTime + "", 10, TimeUnit.MINUTES);
if(loginFailTime >= 10){
stringRedisTemplate.opsForValue().set("userLoginDisableFlag:"+username, "fail", 10, TimeUnit.MINUTES);
return false;
}
return true;
}
Затем определите, является ли это пользовательским исключением. ZwzAuthException
,Если это пользовательское исключение,Затем создайте собственное исключение и информацию,Код следующий.
if (exception instanceof ZwzAuthException){
ResponseUtil.out(response, ResponseUtil.resultMap(false,500,((ZwzAuthException) exception).getMsg()));
}
Пользовательское исключение определяется следующим образом.
@ApiOperation(value = «пользовательское исключение»)
public class ZwzAuthException extends InternalAuthenticationServiceException {
private static final long serialVersionUID = 1L;
private static final String DEFAULT_MSG = "системааутентификация не удалась";
@ApiModelProperty(value = «Содержимое сообщения об исключении»)
private String msg;
public ZwzAuthException(String msg){
super(msg);
this.msg = msg;
}
public ZwzAuthException(){
super(DEFAULT_MSG);
this.msg = DEFAULT_MSG;
}
public ZwzAuthException(String msg, Throwable t) {
super(msg, t);
this.msg = msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
Система управления обычно поддерживает функцию отключения учетной записи, то есть отключение учетной записи. status
Значение устанавливается в определенное состояние, например -1
。
Затем определите, отключена ли учетная запись ненормально. DisabledException
,Если учетная запись отключена, появится соответствующее сообщение.,Код следующий.
if (exception instanceof DisabledException) {
ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"Учетная запись отключена и не может быть использована");
}
Отключен ли пользователь, обычно это поле сущности добрыйиз, например
status
。
Если он не попадает в вышеуказанные три ситуации,Затем будет выдано общее сообщение об ошибке.,Код следующий.
else {
ResponseUtil.out(response, ResponseUtil.resultMap(RESPONSE_FAIL_FLAG,RESPONSE_FAIL_CODE,"система в данный момент недоступна, повторите попытку позже");
}
Полный код выглядит следующим образом.
@ApiOperation(value = "Обратный вызов при ошибке входа")
@Slf4j
@Component
public class AuthenticationFailHandler extends SimpleUrlAuthenticationFailureHandler {
@Autowired
private ZwzLoginProperties tokenProperties;
@Autowired
private StringRedisTemplate stringRedisTemplate;
private static final String LOGIN_FAIL_TIMES_PRE = "LOGIN_FAIL_TIMES_PRE:";
private static final String REQUEST_PARAMETER_USERNAME = "username:";
private static final boolean RESPONSE_FAIL_FLAG = false;
private static final int RESPONSE_FAIL_CODE = 500;
@ApiOperation(value = "Количество неудачных запросов на Авторизацию")
public boolean recordLoginTime(String username) {
String loginFailTimeStr = stringRedisTemplate.opsForValue().get(LOGIN_FAIL_TIMES_PRE + username);
int loginFailTime = 0;
// Количество ошибок
if(!ZwzNullUtils.isNull(loginFailTimeStr)){
loginFailTime = Integer.parseInt(loginFailTimeStr) + 1;
}
stringRedisTemplate.opsForValue().set(LOGIN_FAIL_TIMES_PRE + username, loginFailTime + "", tokenProperties.getLoginFailMaxThenLockTimes(), TimeUnit.MINUTES);
if(loginFailTime >= tokenProperties.getMaxLoginFailTimes()){
stringRedisTemplate.opsForValue().set("userLoginDisableFlag:"+username, "fail", tokenProperties.getLoginFailMaxThenLockTimes(), TimeUnit.MINUTES);
return false;
}
return true;
}
@Override
@ApiOperation(value = "Обратный вызов при ошибке входа")
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) {
if (exception instanceof BadCredentialsException || exception instanceof UsernameNotFoundException) {
recordLoginTime(request.getParameter(REQUEST_PARAMETER_USERNAME));
String failTimesStr = stringRedisTemplate.opsForValue().get(LOGIN_FAIL_TIMES_PRE + request.getParameter(REQUEST_PARAMETER_USERNAME));
//Время ошибок
int userFailTimes = 0;
if(!ZwzNullUtils.isNull(failTimesStr)){
userFailTimes = Integer.parseInt(failTimesStr);
}
int restLoginTime = tokenProperties.getMaxLoginFailTimes() - userFailTimes;
if(restLoginTime < 5 && restLoginTime > 0){
ResponseUtil.out(response, ResponseUtil.resultMap(RESPONSE_FAIL_FLAG,RESPONSE_FAIL_CODE, «Пароль учетной записи неверен, вы также можете попробовать Авторизоваться» + restLoginTime + «Второсортный»);
} else if(restLoginTime < 1) {
ResponseUtil.out(response, ResponseUtil.resultMap(RESPONSE_FAIL_FLAG,RESPONSE_FAIL_CODE, «Повторная попытка превышает лимит, пожалуйста» + tokenProperties.getLoginFailMaxThenLockTimes() + "После разделения Авторизоваться")); } else {
ResponseUtil.out(response, ResponseUtil.resultMap(RESPONSE_FAIL_FLAG,RESPONSE_FAIL_CODE, «Пароль учетной записи неверен»));
}
} else if (exception instanceof ZwzAuthException){
ResponseUtil.out(response, ResponseUtil.resultMap(RESPONSE_FAIL_FLAG,RESPONSE_FAIL_CODE,((ZwzAuthException) exception).getMsg()));
} else if (exception instanceof DisabledException) {
ResponseUtil.out(response, ResponseUtil.resultMap(RESPONSE_FAIL_FLAG,RESPONSE_FAIL_CODE, «Учетная запись отключена и не может быть использована»));
} else {
ResponseUtil.out(response, ResponseUtil.resultMap(RESPONSE_FAIL_FLAG,RESPONSE_FAIL_CODE,"система в данный момент недоступна, повторите попытку позже");
}
}
}
Попросите учащихся создать новую JwtTokenOncePerRequestFilter
фильтр, унаследованный от OncePerRequestFilter
,переписать doFilterInternal
Метод фильтра, код следующий.
@ApiOperation(value = «Настроить фильтр Разрешения»)
@Slf4j
public class JwtTokenOncePerRequestFilter extends OncePerRequestFilter {
private SecurityUtil securityUtil;
@Autowired
private RedisTemplateHelper redisTemplate;
private ZwzLoginProperties zwzLoginProperties;
private static final boolean RESPONSE_FAIL_FLAG = false;
private static final int RESPONSE_NO_ROLE_CODE = 401;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String tokenHeader = request.getHeader(ZwzLoginProperties.HTTP_HEADER);
if(ZwzNullUtils.isNull(tokenHeader)){
tokenHeader = request.getParameter(ZwzLoginProperties.HTTP_HEADER);
}
if (ZwzNullUtils.isNull(tokenHeader)) {
filterChain.doFilter(request, response);
return;
}
try {
UsernamePasswordAuthenticationToken token = getUsernamePasswordAuthenticationToken(tokenHeader, response);
SecurityContextHolder.getContext().setAuthentication(token);
}catch (Exception e){
log.warn("Не удалось выполнить фильтрацию настроенных разрешений" + e);
}
filterChain.doFilter(request, response);
}
@ApiOperation(value = «Определить, является ли Авторизация недействительной»)
private UsernamePasswordAuthenticationToken getUsernamePasswordAuthenticationToken(String header, HttpServletResponse response) {
String userName = null;
String tokenInRedis = redisTemplate.get(ZwzLoginProperties.HTTP_TOKEN_PRE + header);
if(ZwzNullUtils.isNull(tokenInRedis)){
ResponseUtil.out(response, ResponseUtil.resultMap(RESPONSE_FAIL_FLAG,RESPONSE_NO_ROLE_CODE,"Статус авторизоваться недействителен, необходимо войти еще раз!"));
return null;
}
TokenUser tokenUser = JSONObject.parseObject(tokenInRedis,TokenUser.class);
userName = tokenUser.getUsername();
List<GrantedAuthority> permissionList = new ArrayList<>();
if(zwzLoginProperties.getSaveRoleFlag()){
for(String permission : tokenUser.getPermissions()){
permissionList.add(new SimpleGrantedAuthority(permission));
}
} else{
permissionList = securityUtil.getCurrUserPerms(userName);
}
if(!tokenUser.getSaveLogin()){
redisTemplate.set(ZwzLoginProperties.USER_TOKEN_PRE + userName, header, zwzLoginProperties.getUserTokenInvalidDays(), TimeUnit.MINUTES);
redisTemplate.set(ZwzLoginProperties.HTTP_TOKEN_PRE + header, tokenInRedis, zwzLoginProperties.getUserTokenInvalidDays(), TimeUnit.MINUTES);
}
if(!ZwzNullUtils.isNull(userName)) {
User user = new User(userName, "", permissionList);
return new UsernamePasswordAuthenticationToken(user, null, permissionList);
}
return null;
}
public JwtTokenOncePerRequestFilter(RedisTemplateHelper redis, SecurityUtil securityUtil,ZwzLoginProperties zwzLoginProperties) {
this.redisTemplate = redis;
this.securityUtil = securityUtil;
this.zwzLoginProperties = zwzLoginProperties;
}
}
以上代码用于суждение用户из Token статус и определить, действителен ли логин пользователя.。
Попросите учащихся создать новую ImageValidateFilter
фильтр, унаследованный от OncePerRequestFilter
,переписать doFilterInternal
Фильтрационный метод.
Сначала необходимо прочитать фильтр и проверить его внутри интерфейса.,Отпустить, если проверка не требуется,Код следующий.
Boolean filterFlag = false;
for(String requestURI : captchaProperties.getVerification()){
if(pathMatcher.match(requestURI, request.getRequestURI())){
filterFlag = true;
break;
}
}
if(!filterFlag) {
filterChain.doFilter(request, response);
return;
}
Если определено, что требуется фильтрация кода подтверждения, попробуйте прочитать код подтверждения. ID captchaId
и введите значение кода подтверждения code
,существовать Redis Делайте оценочные суждения.
Фильтру необходимо определить, является ли код проверки пустым, просроченным и правильным, и, наконец, обработать его. Код выглядит следующим образом.
String verificationCodeId = request.getParameter("captchaId");
String userInputCode = request.getParameter("code");
if(ZwzNullUtils.isNull(userInputCode) || ZwzNullUtils.isNull(verificationCodeId)){
ResponseUtil.out(response, ResponseUtil.resultMap(RESPONSE_FAIL_FLAG,RESPONSE_CODE_FAIL_CODE, «Код проверки пуст»));
return;
}
String codeAnsInRedis = redisTemplate.opsForValue().get(verificationCodeId);
if(ZwzNullUtils.isNull(codeAnsInRedis)){
ResponseUtil.out(response, ResponseUtil.resultMap(RESPONSE_FAIL_FLAG,RESPONSE_CODE_FAIL_CODE, «Срок действия кода проверки истек, его необходимо заполнить заново»));
return;
}
if(!Objects.equals(codeAnsInRedis.toLowerCase(),userInputCode.toLowerCase())) {
ResponseUtil.out(response, ResponseUtil.resultMap(RESPONSE_FAIL_FLAG,RESPONSE_CODE_FAIL_CODE,"Код проверки неверен"));
return;
}
redisTemplate.delete(verificationCodeId);
filterChain.doFilter(request, response);
Попросите учащихся создать WebSecurityConfig
добрый,Увеличивать @Configuration
аннотация,Определено как настраиваемое,Код следующий.
@ApiOperation(value = "SpringSecurityКонфигурациядобрый")
@Configuration
@EnableMethodSecurity
public class WebSecurityConfig {
}
Затем создайте securityFilterChain
метод, конфигурация Spring Security。
сначала это Конфигурациябелый список,То есть Конфигурации не нужно перехватывать детали интерфейса.,Код следующий.
.requestMatchers("/zwz/dictData/getByType/**","/zwz/file/view/**","/zwz/user/regist","/zwz/common/**","/*/*.js","/*/*.css","/*/*.png","/*/*.ico", "/swagger-ui.html")
затем Конфигурациянамекать Авторизоватьсястраница и Авторизоваться Интерфейс, код следующий.
.formLogin().loginPage("/zwz/common/needLogin").loginProcessingUrl("/zwz/login").permitAll()
затем Конфигурация Войти успешный обратный вызовиметь дело сдобрый,Код следующий.
.successHandler(authenticationSuccessHandler)
затем Конфигурация Обратный вызов при ошибке входаиметь дело сдобрый,Код следующий.
.failureHandler(authenticationFailHandler)
Наконец, настройте фильтры, включая настраиваемые фильтры разрешений и фильтры графического кода проверки. Код выглядит следующим образом.
.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(imageValidateFilter, UsernamePasswordAuthenticationFilter.class);
Полный код показан ниже.
@ApiOperation(value = "SpringSecurityКонфигурациядобрый")
@Configuration
@EnableMethodSecurity
public class WebSecurityConfig {
@Autowired
private ZwzLoginProperties zwzLoginProperties;
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
private AuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
private AuthenticationFailHandler authenticationFailHandler;
@Autowired
private ZwzAccessDeniedHandler zwzAccessDeniedHandler;
@Autowired
private ImageValidateFilter imageValidateFilter;
@Autowired
private RedisTemplateHelper redisTemplate;
@Autowired
private SecurityUtil securityUtil;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests().requestMatchers("/zwz/dictData/getByType/**","/zwz/file/view/**","/zwz/user/regist","/zwz/common/**","/*/*.js","/*/*.css","/*/*.png","/*/*.ico", "/swagger-ui.html").permitAll()
.and().formLogin().loginPage("/zwz/common/needLogin").loginProcessingUrl("/zwz/login").permitAll()
.successHandler(authenticationSuccessHandler).failureHandler(authenticationFailHandler).and()
.headers().frameOptions().disable().and()
.logout()
.permitAll()
.and()
.authorizeHttpRequests()
.anyRequest()
.authenticated()
.and()
.cors().and()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling().accessDeniedHandler(zwzAccessDeniedHandler)
.and()
.authenticationProvider(authenticationProvider())
.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(imageValidateFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public UserDetailsService userDetailsService() {
return username -> userDetailsService.loadUserByUsername(username);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService());
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
@Bean
public JwtTokenOncePerRequestFilter authenticationJwtTokenFilter() throws Exception {
return new JwtTokenOncePerRequestFilter(redisTemplate, securityUtil, zwzLoginProperties);
}
}
Попросите учащихся запустить серверную часть проекта и сначала получить к ней доступ с помощью браузера. http://localhost:8081/
,система автоматически перенаправляет на страницу авторизации советов,Как показано ниже.
Затем получите доступ к бесплатному интерфейсу входа в систему. http://localhost:8081/zwz/dictData/getByType/sex
,Было обнаружено, что данные можно было прочитать нормально.
Наконец, в этой статье SpringBoot3 успешно интегрирован с SpringSecurity и реализована настраиваемая фильтрация разрешений интерфейса.