Данный проект помогает разработчикам быстро, просто и без настройки интегрировать Shiro-фреймворк.
Демо: https://github.com/justsosoG/idong/tree/master
https://apidoc.gitee.com/justsosoG/easy-shiro/
Рекомендуется использовать последнюю версию вместо загрузки исходного кода с GitHub для самостоятельной компиляции.
Пример использования в Spring Boot:
<dependency>
<groupId>org.njgzr</groupId>
<artifactId>easy-shiro</artifactId>
<version>${latest.version}</version>
</dependency>
Актуальную версию можно найти здесь: https://mvnrepository.com/artifact/org.njgzr/easy-shiro
Создайте класс конфигурации и добавьте аннотацию @EnableEasyShiro:
@EnableEasyShiro
@Configuration
public class LoginConfig {
}
Для проектов на Spring Boot достаточно добавить аннотацию к стартовому классу:
@SpringBootApplication
@EnableEasyShro
public class Demo2Application {
public static void main(String[] args) {
SpringApplication.run(Demo2Application.class, args);
}
}
Реализуйте четыре интерфейса: ConfigGetService, LoginResultService, SecurityService и AuthorizedUser.
Обратите внимание: если используется база данных, то пароли должны быть зашифрованы с использованием метода new Password(строка для шифрования).toString(). В этом проекте используется безопасный способ шифрования, который обеспечивает уникальность зашифрованных паролей.
Пример реализации:
@Service
public class ServiceImpl implements ConfigGetService,LoginResultService,SecurityService{
/**
* principal — это логин пользователя.
*/
@Override
public AuthorizedUser findByPrincipal(Object principal) {
// В процессе разработки следует получать данные из базы данных, используя параметр principal в качестве логина.
if (principal instanceof String) {
User user = userService.findByLoginName((String) principal);// Локальный аккаунт
if (user == null)
return null;
AuthorizedUserInfo info = new AuthorizedUserInfo();// Здесь AuthorizedUserInfo реализует интерфейс AuthorizedUser
Long orgid = user.getOrganizationId();
info.setUploadUrl(user.getUploadUrl());
info.setDisplayName(user.getDisplayName());
info.setId(user.getId());
info.setLoginName(user.getLoginName());
info.setMobile(user.getMobile());
info.setType(user.getType());
info.setOrganizationId(orgid);
info.setDefaultCauseId(user.getDefaultCauseId());
info.setAddress(user.getAddress());
info.setPermissions(permissions);
info.setRoles(roles);
log.info(info.toString());
return info;
// Здесь info будет возвращена на фронтэнд.
// Также можно использовать AuthorizedUserInfo info = (AuthorizedUserInfo) SecurityUtil.getCurrentUser(); для получения информации.
}
return null;
}
@Override
public Password findPassword(AuthorizedUser user) {
// Во время разработки следует извлекать данные из базы данных, используя идентификатор пользователя для поиска соответствующей записи в базе данных и возврата поля пароля. Обратите внимание, что здесь должен быть возвращён тип Password.
User user = userService.findById(authorizedUser.getId());
return user == null ? null : user.getPassword();
}
/**
* Обратный вызов после успешного входа.
*/
@Override
public void loginSuccess(Long userId, String loginName, String terminal, String addr, String ip,String os,String browser) {
System.err.println(loginName+" успешно вошёл в систему");
}
/**
* Установка максимального количества одновременных входов для одного аккаунта.
*/
@Override
public Long maxSessionCount() {
return 2L;
}
}
``` **Текст запроса:**
* 免认证的接口
*/
@Override
public List<String> anons() {
List<String> dList = Lists.newArrayList();
return dList;
}
/**
* 返回null则基于内存模式
*/
@Override
public StringRedisTemplate getStringRedisTemplate() {
return stringRedisTemplate;
}
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* 系统标识符
*/
@Override
public String getAppId() {
return "Idong";
}
/**
* web应用的令牌有效时间,返回null则默认为30分钟
*/
@Override
public Long webExpireTime() {
return 30 * 60 * 1000L;
}
/**
* 手机应用的令牌有效时间,返回null则默认为1个月
*/
@Override
public Long appExpireTime() {
return 30 * 60 * 1000L;
}
/**
* pc应用的令牌有效时间,返回null则默认为1天
*/
@Override
public Long pcExpireTime() {
return 30 * 60 * 1000L;
}
/**
* 登录请求中用户名的字段,返回null则默认为username
*/
@Override
public String loginUserNameParam() {
return null;
}
/**
* 登录请求中密码的字段,返回null则默认为password
*/
@Override
public String loginPasswordParam() {
return null;
}
/**
* 请求头中的令牌字段,返回null则默认为 token
*/
@Override
public String headerToken() {
return "myToken";
}
/**
* 登录接口的地址,返回null则默认是 /login
*/
@Override
public String loginUrl() {
return null;
}
/**
* 登出回调
*/
@Override
public void logout(Long userId, String loginName) {
// TODO Auto-generated method stub
}
/**
* 登录失败的回调
*/
@Override
public void loginFail(String loginName, Exception e) {
// TODO Auto-generated method stub
}
/**
* 登录请求中验证码的字段,返回null则默认为captchaCode
*/
@Override
public String captchaParam() {
return null;
}
/**
* 最大的错误次数,如果超过该数字或者返回0,系统将校验验证码
*/
@Override
public int maxClfCount() {
return 2;
}
/**
* 验证码的长度,最长6位,最短4位,如为算术验证码,则默认是两个数字的算术题
*/
@Override
public int captchaLenth() {
return 4;
}
/**
* 验证码图片的大小,格式为 宽,高 ,逗号为英文状态的逗号,返回null则默认 110,40
*/
@Override
public String captchaSize() {
return "120,60";
}
/**
* 是否开启验证码
*/
@Override
public boolean enableCaptcha() {
return true;
}
/**
* 验证码类型,目前可选的为 specCaptcha,gifCaptcha,chineseCaptcha,chineseGifCaptcha,arithmeticCaptcha,
* 如果返回null,则默认随机,中文验证码存在问题,暂时不推荐使用
* 可选值参考org.njgzr.security.enums.CaptchaType
* 若返回随意字符串,则默认specCaptcha
*/
@Override
public String captchaType() {
return null;
}
**Перевод текста на русский язык:**
* Интерфейс без аутентификации
*/
@Override
public List<String> анонимный() {
Список dList = новый ArrayList();
вернуть dList;
}
/**
* Возвращает null, тогда используется режим памяти
*/
@Override
общедоступный StringRedisTemplate getStringRedisTemplate() {
возврат stringRedisTemplate;
}
@Autowired
частный StringRedisTemplate stringRedisTemplate;
/**
* Идентификатор системы
*/
@Override
публичный String getId() {
возвращение «Идонг»;
}
/**
* Время действия токена для веб-приложения, возвращает null по умолчанию 30 минут
*/
@Override
общедоступное длинное время истечения срока действия веб-интерфейса() {
возвращает 30 * 60 * 1000L;
}
/**
* Срок действия токена мобильного приложения, возвращает null по умолчанию один месяц
*/
@Override
общедоступное длительное время истечения срока действия приложения() {
возвращает 30 * 60 * 1000L;
}
/**
* Срок действия токена настольного приложения, возвращает null по умолчанию один день
*/
@Override
общедоступное долгое время истечения срока действия ПК() {
возвращает 30 * 60 * 1000L;
}
/**
* Поле имени пользователя в запросе на вход, возвращает null по умолчанию username
*/
@Override
общедоступная строка loginUserNameParam() {
возвратить null;
}
/**
* Поле пароля в запросе на вход, возвращает null по умолчанию password
*/
@Override
общедоступная строка loginPasswordParam() {
возвратить null;
}
/**
* Поле токена в заголовке запроса, возвращает null по умолчанию token
*/
@Override
общедоступная строка headerToken() {
возвращается «myToken»;
}
/**
* Адрес интерфейса входа, возвращает null по умолчанию /login
*/
@Override
общедоступная строка loginUrl() {
возвратить null;
}
/**
* Выход из системы
*/
@Override
общедоступный выход (длинный идентификатор пользователя, строка loginName) {
// TODO Автоматически сгенерированный метод-заглушка
}
/**
* Обратный вызов при неудачном входе
*/
@Override
общедоступный логин не удался (строка loginName, исключение e) {
// TODO Автоматически сгенерированный метод-заглушка
}
/**
* Поле кода проверки в запросе входа, возвращает null по умолчанию captchaCode
*/
@Override
общедоступная строка captchaParam() {
возвратить null;
}
/**
* Максимальное количество ошибок, если оно превышает это число или возвращается 0, система проверит код подтверждения
*/
@Override
общедоступные int maxClfCount() {
возвращает 2;
}
/**
* Длина кода подтверждения, максимум 6 цифр, минимум 4 цифры, если это арифметический код подтверждения, то по умолчанию это арифметическая задача с двумя цифрами
*/
@Override
общедоступный int captchaLength() {
возвращает 4;
}
/**
* Размер изображения кода подтверждения, формат 宽, высота, запятая — английская запятая, возвращает null по умолчанию 110, 40
*/
@Override
общедоступная строка captchaSize() {
возвращается "120, 60";
}
/**
* Включить ли код подтверждения
*/
@Override
общедоступная логическая поддержка капчи() {
возвращает истину;
}
/**
* Тип кода подтверждения, в настоящее время доступны варианты specCaptcha, gifCaptcha, chineseCaptcha, chineseGifCaptcha, arithmeticCaptcha, если возвращается null, то по умолчанию случайный, китайский код подтверждения имеет проблемы, временно не рекомендуется использовать
* Доступные значения см. в org.njgzr.security.enums.CaptchaType.
* Если возвращается произвольная строка, то по умолчанию specCaptcha
*/
@Override
общедоступная строка типа капчи() {
возвращать null;
}}
В тексте запроса нет кода на каком-либо языке программирования, гиперссылок, специальных тегов форматирования в markdown, html, yaml, json, plantuml и других. **Срок действия токена и льготный период**
Если срок действия токена истёк, то в течение следующей минуты им всё ещё можно пользоваться. Это сделано для того, чтобы запросы, обработка которых ещё не завершена, могли вернуться нормально.
В течение этой минуты при возврате запроса в заголовках ответа будет возвращаться новый токен, который также будет записан в cookie. В процессе реальной разработки, как только вы обнаружите, что в response headers есть возвращаемое значение токена, просто замените старый токен на новый.
Также вы можете создать таймер, который будет периодически обращаться к определённому интерфейсу, чтобы гарантировать актуальность вашего токена.
**Адрес верификационного кода:** http://ip:port/captcha
Когда требуется верификационный код?
```json
{
"code": 501,
"data": {
"captchaEnabled": true
},
"desc": "Ошибка верификации",
"success": false,
"time": 1576639456428
}
Этот ответ означает, что требуется верификация.
Как ограничить поток интерфейса?
Добавьте аннотацию @LxRateLimit(perSecond = 10.0) к нужному интерфейсу.
perSecond указывает количество вызовов этого интерфейса в секунду.
Обратите внимание:
Все интерфейсы возвращают тип Result.
@LxRateLimit(perSecond = 10.0)
@RequestMapping(value="/getStr",method={RequestMethod.POST})
public Result getString() {
return Result.success("hello-"+new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
}
Как провести проверку роли или прав доступа для интерфейса?
Сначала определите Set permissions и Set roles в классе AuthorizedUser.
Затем присвойте значения этим полям в методе findByPrincipal класса SecurityService.
Наконец, добавьте следующие аннотации к интерфейсу, требующему аутентификации:
@LxRateLimit(perSecond = 10.0)
@RequestMapping(value="/getStr",method={RequestMethod.POST})
@RequiresRoles(value = { "role1","role2" })
@RequiresPermissions(value = { "per1","per2" })
public Result getString() {
return Result.success("hello-"+new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )