Широ
Широ - это проект с открытым исходным кодом в Apache, мы называем его Apache Shiro. Это очень простая в использовании структуру безопасности с Java Projects, обеспечивая аутентификацию, авторизацию, шифрование и управление сеансами. Как и Spring Security, это структура безопасности разрешения. Однако, по сравнению с Spring Security, Shiro использует относительно простой, простой для понимания и простой в использовании метод авторизации. Широ - легкая структура. Это намного проще, чем безопасность и не так сложно, как безопасность. Для более подробных представлений вы можете в основном учиться на его официальном веб -сайте (http://shiro.apache.org/), что в основном предоставляет следующие функции:
(1) Аутентификация (аутентификация)
(2) разрешение (авторизация)
(3) Управление сессиями (управление сеансом)
(4) Криптография (шифрование)
Прежде всего, служба аутентификации, то есть через нее, вы можете завершить аутентификацию идентификации, позволяя ей определить, является ли пользователь реальным участником.
Во -вторых, авторизованная служба, чтобы сказать, является сервисом «контроль доступа», то есть позволить ей определить, какие разрешения имеют пользователь. Говоря, это должно дать ему, какие разрешения операции, оценив, какую роль является пользователь.
Затем есть служба управления сеансом. В настоящее время независимая структура управления сеансами отличается от сеанса HTTP, с которой мы знакомы.
Наконец, она также предоставляет услуги криптографии (шифрования), инкапсулируя многие криптографические алгоритмы.
Сегодня я не буду говорить об этом и сосредоточиться на ее функции управления разговорами. На самом деле, это то, что должно быть вовлечено почти все сети.
Прежде чем говорить о службе управления сеансами Широ, давайте рассмотрим, как мы сделали предыдущее управление сессиями.
1. Сначала мы напрямую использовали механизм сеанса HTTP веб -сервера. То есть, если пользователь входит в первый раз, веб -контейнер создаст сеанс для запроса, а затем сохранит сеанс. Передавая соответствующий сеанс в качестве файла cookie клиенту.
Если клиент снова отправит запрос на этот сервер, SessionID будет автоматически переведен. Затем веб -сервер определит, находится ли сеанс в памяти на основе SessionID, принесенного клиентом (сеанс имеет время истечения срока действия и может быть настроен в файле web.xml). Если соответствующий сеанс не может быть найден, это означает, что время истечения сессии прошло. В настоящее время веб -сервер снова создаст для него сеанс, а затем передаст новый SessionID клиенту, как и раньше.
Поэтому мы можем использовать этот механизм для управления сеансом входа в систему пользователя в программе. Например, после того, как первый вход пользователя будет успешным, мы храним основную информацию пользователя в сеансе (например: session.setAttribute("user", "userInfo") ). В следующий раз, когда пользователь снова посетит, мы получаем пользовательскую информацию в текущем сеансе на основе информации пользователя
( session.getAttribute("user") ), чтобы определить, истек ли пользователь. Если его нельзя получить, пользователю будет предложено снова войти в систему.
2. Второй метод-передавать место, где информация хранится в сторонних носителях, таких как кэш, мемкаш или Redis. Этот метод в основном принимается из -за появления распределенных систем.
В этом случае нам нужно генерировать SessionId сами. Как правило, мы будем использовать определенный префикс ( user:login:token ) и добавить userid или timestamp. Затем мы будем использовать этот SessionID в качестве ключа кеша, а также информацию пользователя в качестве значения, и сохраним его в кэше, и установим время неверно:
jedisclient.set (tokenkey, jsonutil.tojsonstring (userinfo)); jedisclient.expire (tokenkey, token_lose_seconds);
Нам также необходимо передать сгенерированный токенк -дай -клиент через файлы cookie: CookieUtils.setCookie(request, response, "TT_TOKEN", tokenKey);
Таким образом, когда пользователь посетит в следующий раз (определяет перехватчик), мы можем извлечь соответствующий токки из печенья, а затем использовать этот токенкей, чтобы перейти в кэш, чтобы получить соответствующее значение. Если его нельзя получить, это означает, что ключ истек, и пользователю предложено снова войти в систему.
Примечание. Токенки важен, это концентратор, соединяющий сторону кэша и клиента.
3. Последний - наш метод Широ, и идея похожа. Код довольно прост, поэтому я просто загрузию код:
1) Создать новый файл ApplicationContext-shiro.xml:
<? xml version = "1.0" Encoding = "UTF-8"?> <Beans xmlns = "http://www.springframework.org/schema/beans" xmlns: context = "http://www.springframework.org/schema/context" xmlns: p = "http://www.springframework.org/schema/p" xmlns: aop = "http://www.springframework.org/schema/tx" xmlns: xsi = "http://www.w3. xsi: schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.spramework.org/schema/context http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/Util http://www.springframework.org/schema/util-tlil-4.0.x.spramework.org/schema/utm. id = "shirofilter"> <name = "securitymanager" ref = "SecurityManager"> </property> <name = "loginurl" value = "/loginPage"> </properation> <name = "unauthorizedUrl" value = "/pages/unauthorized.jsp"/> name name = "filetrchaindefinditions* valueThaUts>/valueTHAPTS/valueThaUTS>/valueThaUTS* valueThaUTS>/valueTHAPTS* valueThaUTS* ancon vallations>/vallized. = anon </value> </property> </bean> <bean> <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"></property> <property name="arguments" ref="securityManager"></property> </bean> <bean id="securityManager"> <property name="cacheManager" ref="cacheManager"></property> <property name="sessionManager" ref="sessionManager"></property> </bean> <bean id="sessionManager"> <property name="sessionDAO" ref="sessionDAO"></bean> //This class needs to be implemented by itself<bean id="cacheManager"></bean></beans>
2) Настройка соответствующего фильтра в web.xml:
<filter> <filter-name> shirofilter </filter-name> <filter-class> org.springframework.web.filter.delegatingfilterproxy </filter-class> <init-param> </param-name> targetFilterLifeCycle </param-name> <param-value> true </param-value> </param-value> </param-value> </param-value> </param-value> </param-value> </param-value> </param-value> </param-value> </param-value> </param-value <Filter-Mapping> <Filter-name> Shirofilter </filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
3) Напишите класс реализации, наследует AbstractSessionDao и реализуйте соответствующий метод.
пакет com.jdd.core.shiro; import com.smart.core.redis.redismanager; import org.apache.shiro.session.session; import org.apache.shiro.session.unknownsessionException; импорт org.apache.shiro.session.mgt.eis.abstractsessionDaoDao; org.springframework.beans.factory.annotation.autowired; импорт org.springframework.util.serializationUtils; импорт java.io.*; импорт java.util.arraylist; import java.util.collection; открытый класс MySessionDao ExtrabledessessessionDao {@Autrowarted.agrection; @Override public void update (сеанс сеанса) Throws inknownSessionException {redismanager.set (serializationUtils.serialize (session.getid (). ToString ()), serializationUtils.serialize (session)); Redismanager.expire (serializationutils.serialize (session.getid (). ToString ()), 60); } @Override public void delete (сеанс сеанса) {redismanager.del (serializationUtils.serialize (session.getid (). ToString ())); } @Override Public Collection <session> GetActivesSessions () {return New ArrayList <session> (); } @Override защищено сериализуемая docReate (сеанс сеанса) {// Это когда вы первой доступ, создайте SessionId Serializable SID = this.GeneratesessionId (Session); DessageSessionId (Session, SID); redismanager.set (serializationutils.serialize (session.getid (). ToString ()), serializationUtils.serialize (session)); Redismanager.expire (serializationutils.serialize (session.getid (). ToString ()), 60); вернуть Сид; } @Override защищенный сеанс DoreAdsession (Serializable Serializable) {// Этот метод фактически для чтения сеанса через SessionId. Каждый раз, когда вы читаете его, время сбоя должно быть сброшенным байтом [] aa = redismanager.get (serializationutils.serialize (serializable.tostring ())); Session Session = (Session) serializationUtils.deserialize (aa); RedisManager.Set (serializationUtils.serialize (serializable.toString ()), serializationutils.serialize (session)); Redismanager.expire (serializationutils.serialize (serializable.tostring ()), 60); возвратный сеанс; }}4) Следующим шагом является получение сеанса Shiro в логике после успешного входа, а затем установить информацию пользователя в
пакет com.smart.controller; import com.smart.pojo.user; import com.smart.service.userservice; import org.apache.shiro.securityutils; импорт org.apache.shiro.mgt.securitymanager; импорт org.apache.shiro.subject.subject; org.slf4j.loggerfactory; import org.springframework.beans.factory.annotation.autowired; import org.springframework.steretype.controller; import org.springframework.ui.model; импорт org.spramework.web.bind.annotation. javax.servlet.http.httpservlectrequest; import javax.servlet.http.httpservletresponse;@controller@requestmapping ("/user") открытый класс usercontroller {@autowired private userservice userservice; @Autowired Private SecurityManager SM; // Inject SecurityManager Private Logger logger = loggerFactory.getLogger (userController.class); @Requestmapping (value = "/loginPage") public String loginPage () {return "user/userLogin"; } @RequestMapping (value = "/userLogin", method = requestMethod.post) public String userLogin (@RequestParam (value = "name") String name, @RequestParam (value = "pwd") String pwd, модель модели) {logger.info ("enter userLogin ..."); User user = userservice.getuserbynameandpassword (имя, pwd); if (user == null) {logger.info («Пользователь не существует ...»); model.addattribute ("login_error", "Имя пользователя или ошибка пароля"); вернуть "пользователь/userLogin"; } SecurityUtils.seTecurityManager (sm); Субъект CurrentUser = SecurityUtils.getSubject (); currentUser.getSession (). setattribute ("login_user", user); вернуть "перенаправление:/сотрудник/список"; }}Получите текущего пользователя, в Shiro это тема, затем получите соответствующий сеанс и установите информацию пользователя. Похоже ли это немного похоже на работу сеанса HTTP? Хаха.
5) Наконец, определите перехватчик SpringMVC для получения пользовательской информации в соответствующем сеансе в перехватчике. Если его нельзя получить, он прыгнет к интерфейсу входа в систему.
пакет com.smart.core.shiro; import com.smart.pojo.user; import org.apache.shiro.securityutils; import org.apache.shiro.mgt.securitymanager; import org.apache.shiro.subject.subject; import.shippuct. org.springframework.beans.factory.annotation.autowired; импорт org.springframework.web.servlet.handlerinterceptor; import org.springframework.web.servlet.modelandView; import javax.servlet.htp.httpserveltrequest; javax.servlet.http.httpservletresponse; открытый класс logininterceptor реализует handlerinterceptor {private logger logger = loggerfactory.getlogger (logininterceptor.class); @Autowired Private SecurityManager SM; @Override public boolean prehandle (httpservletrequest httpservletrequest, httpservletresponse httpservletresponse, объект o) Throws Exception {logger.info ("Введите LoginInterceptor ..."); Httpservletrequest request = httpservletrequest; Httpservletresponse response = httpservletresponse; logger.info ("запрос uri ===>"+request.getRequesturi ()); // Если это запрос на страницу входа в систему, он не будет перехвачен, в противном случае он попадет в мертвый цикл if (request.getRequesturi (). Содержит ("loginPage") || request.getRequesturi (). Содержит ("userLogin")) {return true; } else {securityUtils.seTecurityManager (sm); Субъект CurrentUser = SecurityUtils.getSubject (); Object obj = currentUser.getSession (). GetAttribute ("login_user"); if (obj == null) {response.sendredirect ("http: // localhost: 8080/user/loginpage"); вернуть ложь; } else {user user = (user) obj; if (user == null || user.getname () == null) {response.sendreedirect ("http: // localhost: 8080/user/loginpage"); вернуть ложь; } else {return true; }}}} @Override public void poshandle (httpservlectrequest httpservletrequest, httpservletresponse httpservletresponse, Object o, ModelandView modelandView) throws exectors {} @Override public httpservletresponse, Object O, Exception e) бросает исключение {}}Это в основном здесь. Если вы обращаетесь к информации на домашней странице прямо сейчас, она автоматически перейдет на страницу входа в систему.
Суммировать
Вышеуказанное - все содержание этой статьи. Я надеюсь, что содержание этой статьи имеет определенную справочную ценность для каждого обучения или работы. Если у вас есть какие -либо вопросы, вы можете оставить сообщение для общения. Спасибо за поддержку Wulin.com.