O que é Shiro
O Shiro é uma estrutura de permissão de código aberto para a plataforma Java para autorização de autenticação e acesso. Especificamente, o suporte para os seguintes elementos é atendido:
P: Suporte para o grupo?
R: Shiro não suporta as permissões de definição de grupos por padrão.
P: Ele pode atender às necessidades de alocação de papéis para grupos?
R: A extensão do reino pode suportar a atribuição de funções a grupos, que é realmente atribuir permissões a todos os usuários no grupo.
P: Suporte para permissões de dados? Definido em um sistema de negócios?
R: Shiro implementa apenas o controle sobre as permissões de operação, que é usada para ocultar ou exibir os elementos de controle front-end e verificar as permissões de acesso a recursos. As permissões de dados estão intimamente relacionadas a necessidades de negócios específicas, e o próprio Shiro não pode controlar as permissões de dados.
P: Alocação de permissão dinâmica?
R: Extend org.apache.shiro.realm.realm para apoiar a alocação de permissão dinâmica.
P: integrar -se à primavera?
R: Ele pode suportar integração com a primavera e Shiro também suporta tags JSP.
No blog anterior, conversamos sobre os dois maiores recursos de Shiro, autenticação e autorização. O sinal único também faz parte da autenticação. Por padrão, a Shiro implementou a integração com o CAS para nós, e tudo bem se adicionarmos algumas configurações integradas.
1. Adicione o pacote Shiro-Cas
<!-Shiro integra o CAS Single Point-> <Depence> <PuerpId> org.apache.shiro </groupiD> <ArtifactId> Shiro-Cas </sutifactId> <versão> 1.2.4 </versão </dependency>
2. Adicione a configuração de sinal único
Aqui, publiquei todas as configurações para facilitar a referência e instruções detalhadas foram adicionadas à configuração.
pacote com.chhliu.springboot.shiro.config; importar java.util.linkedhashmap; importar java.util.map; importar javax.servlet.filter; importar org.apache.shiro.cache.ehcache.ehcachemanager; importar org.apache.shiro.cas.casfilter; importar org.apache.shiro.cas.cassubjectFactory; importar org.apache.shiro.spring.lifecycleBeanPostProcessor; importar org.apache.shiro.spring.security.intercept.authorizationAttributesourCeadvisor; importar org.apache.shiro.spring.web.shirofilterfactorybean; importar org.apache.shiro.web.mgt.defaultwebecurityManager; importar org.jasig.cas.client.session.SingLeSignOutFilter; importar org.jasig.cas.client.session.singLeSignouthTtpSessionListener; importar org.springframework.aop.framework.autoproxy.defaultAdvisorautoProxycreator; importar org.springframework.boot.web.servlet.filterRegistrationBean; importar org.springframework.boot.web.servlet.servletListenerRegistrationBean; importar org.springframework.context.annotation.bean; importar org.springframework.context.annotation.configuration; importar org.springframework.context.annotation.dependson; importar org.springframework.core.ordered; importar org.springframework.core.annotation.order; importar org.springframework.web.filter.delegatingFilterProxy; /*** Configuração Shiro** O núcleo do Apache Shiro é implementado através do filtro, assim como o Springmvc usa o DispachServlet para controlá -lo. Como usamos o filtro *, geralmente podemos adivinhar que a filtragem e a verificação de permissão são feitas por meio das regras da URL, por isso precisamos definir uma série de regras e direitos de acesso sobre URLs. * * @author chhliu */@configuration public class Shiroconfiguration {// Endereço do servidor Cas public static final String CasserverurlPrefix = "http://127.0.0.1"; // Cas Login Page Endereço Public Static Final String CasLoginurl = CASSERVERURURLPREFIX + "/LOGIN"; // CAS Página de logout Endereço Public Static Final String CasLogouturl = CASSERVERURURLPREFIX + "/LOGOUT"; // O endereço de serviço atual fornecido pelo projeto para a sequência final do mundo estático do mundo ShiroserverurlPrefix = "http://127.0.1.28:8080"; // casfilter urlpattern public static final string casfilterurlpattern = "/index"; // Endereço de login public static final string loginurl = casloginurl + "? // Endereço de logout (o CASSERVER permite a função de salto de serviço e você precisa ativar Cas.logout.followServicedirects = true no arquivo WebApps/Cas/Web-Inf/Cas.Properties) Public Static String Logouturl = Caslogouturl+"? Serviço ="+Loginurl; // Login Endereço bem -sucedido // Public Static Final String LogInsuccessUrl = "/Index"; // Autenticação de permissão Falha no endereço de salto público estático final string não autorizada = "/error/403.html"; / ** *SecurityManager Instantiate, esta classe é a classe principal de shiro */ @return */ @Bean public DefaultWeburCurityManager SecurityManager () {defaultWeburCarguardManager SecurityManager = new DefaultWebUsCurityManager (); SecurityManager.SetRealm (myshirocasRealm ()); // <!-Cache de informações sobre autorização/autenticação do usuário, usando o ehcache cache-> segurança // Especifique o sujeito do sujeito. Se você deseja implementar a função Remember Me do CAS, precisará usar o seguinte CassubjectFactory e defini -lo como SecurityManager Subjetivo SecurityManager.SetSubjectFactory (new CassubjectFactory ()); Retornar SecurityManager; } / *** Configurar cache* @return* / @Bean public Ehcachemanager getEhcachemanager () {ehcachemanager em = new ehcachemanager (); em.SetCachemanageRerConfigFile ("ClassPath: config/ehcache-shiro.xml"); devolver -os; } /*** Configure o reino. Como estamos usando o CASRALM, a função de assinatura única foi integrada * @param cachemanager * @return */ @Bean public myshirorealm myshirocasRealm () {myshirorealm realm = new myshirorealm (); // CAS Login Server Endereço Prefixo RealM.SetCasserVeurLPrefix (shiroconfiguration.casserverurlPrefix); // Endereço de retorno de chamada do cliente, endereço de salto após o login ser bem -sucedido (seu próprio endereço de serviço) RealM.SetCasService (shiroconfiguration.shiroserverurlPrefix + shiroconfiguration.casfilterurlPattern); // A função padrão após o login ser bem -sucedida, aqui os padrões da função do usuário realm.SetDefaULtroles ("Usuário"); devolver reino; }/ ** * Registre um único ouvinte * @return */ @suppresswarnings ({"RawTypes", "desmarcado"}) @Bean @Order (ordened.highest_precedence) // a prioridade é maior que o CAS Public ServerlistenerRegistrationBean <?> ServletListenerRegistrationBean (); bean.setListener (novo singleSignouthttpSessionListener ()); bean.setEnabled (true); Retornar Bean; } / ** * Registre filtro de desligamento único * @return * / @Bean public filterRegistrationBean SingleSignOutFilter () {filterRegistrationBean bean = new FilterRegistrationBean (); bean.setName ("SingleSignOutFilter"); bean.setFilter (novo singleSignOutFilter ()); bean.addurlpatterns ("/*"); bean.setEnabled (true); Retornar Bean; } / ** * Registre DelegatingFilterProxy (shiro) * / @Bean public filterRegistrationBean DelegatingFilterProxy () {filterRegistrationBean filterRegatration = new FilterRegistrationBean (); filterRegistration.setFilter (New DelegatingFilterProxy ("Shirofilter")); // Este valor é falso por padrão, indicando que o ciclo de vida é gerenciado pelo SpringApplicationContext. Definido como true significa que o servletContainer é gerenciado pelo filtroRegistration.addinitParameter ("TargetFilterLifeCycle", "True"); filterRegistration.setEnabled (true); filterRegistration.addurlpatterns ("/*"); retornar o registro do filtro; } /** * This class can ensure that the init or destory method of the shiro object that implements the org.apache.shiro.util.Initializable interface is automatically called, * without manually specifying the init-method or destory-method method* Note: If this class is used, there is no need to manually specify the initialization method and the destroy method, otherwise an error will occur* @return */ @Bean(name = "LifeCycleBeanPostProcessor") Public LifeCycleBeanPostProcessor getLifeCycleBeanPostProcessor () {return New LifeCycleBeanPostProcessor (); } /*** As duas configurações a seguir são usadas principalmente para ativar o suporte da anotação Shiro AOP. Use o método proxy; Portanto, você precisa ativar o suporte ao código; * @RETURN */ @Bean @dependson ("LifeCycleBeanPostProcessor") Public DefaultAdvisorautoProxycreator GetDefaultAdvisorAutoProxycreator () {defaultAdvisorAutoProxycreator daap = new DefaultAdAdVisorAxycReator (New DefaultAdAdVisorAxycreator; daap.setProxyTargetClass (true); retornar daap; } /** * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); AuthorizationAttributesourCeadvisor.SetSecurityManager (SecurityManager); Retorno AuthorizationAttributesourCeadvisor; } / *** filtro CAS* @return* / @Bean (name = "casfilter") public casfilter getCasFilter () {casfilter casfilter = new Casfilter (); casfilter.setName ("casfilter"); casfilter.setEnabled (true); // O URL que salta após o login falhou, ou seja, Shiro executa o método do CasRealm para verificar o Tiket Casfilter.SetFailureurl (Loginurl); // optamos por abrir a página de login após a autenticação Casfilter.setLoginurl (Loginurl); retornar casfilter; } / ** * Crie e inicialize o Shirofilter usando o modo de fábrica * @param Segurança novo ShirofilterFactoryBean (); // SecurityManager deve ser definido ShirofilterFactoryBean.SetSecurityManager (SecurityManager); // Se você não definir o padrão, ele encontrará automaticamente a página "/login.jsp" no diretório raiz do projeto da web shirofilterfactorybean.setloginurl (loginurl); / * * A conexão a ser redirecionada após o login ser bem -sucedida. Se não estiver definido, ele saltará para o URL anterior por padrão. * Por exemplo, você primeiro inseriu http: // localhost: 8080/userlist no navegador, mas agora o usuário não está conectado, para que ele entre na página de login. Depois que a autenticação de login for passada, a página * pulará automaticamente para a página http: // localhost: 8080/userlist em vez da página de índice após o login bem -sucedido. Este campo não é recomendado para ser definido */ // shirofilterFactoryBean.SetSUCCESSURL (LOGINSUCSUSURL); // Defina acesso não autorizado à página ShirofilterFactoryBean.SetUNAuthorizedUrl (Unauthorizedurl); / * * Adicione o Casfilter ao Shirofilter. Observe que o Casfilter precisa ser colocado na frente do Shirofilter, * para garantir que o programa insira a autenticação de ponto único antes de inserir o login do Shiro Login */ map <string, filter> filters = new LinkedHashMap <> (); filters.put ("casfilter", casfilter); // O logout foi substituído por logout de ponto único // filters.put ("logout", logoutFilter ()); ShirofilterFactoryBean.SetFilters (filtros); loadshirofilterchain (ShirofilterFactoryBean); Retornar ShirofilterFactoryBean; } /*** Carregar regras de controle de permissão Shirofilter (Leia o banco de dados e configurar), as informações de função /permissão são fornecidas pelo objeto MyshirocasRealm. DOGETAUTHORIZAÇÃO IMPLEMPERENCIMENTAÇÃO. * This part of the rules will be placed in the database during production* @param shiroFilterFactoryBean */ private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean){ //////////////////////////////////////// The following rules are best configured in the configuration arquivo. Observe que o filtro adicionado aqui precisa ser ordenado; portanto, use o LinkedHashmap //////////////////////////////////////////////////////////tinciou, filtroundhapinitionMap = new LinkedHashmap filterChainndefinitionMap.put (casfilterurlpattern, "casfilter"); // 2. Solicitações que não interceptem o filtroCHAINDefinitionMap.put ("/css/**", "anon"); filterChainndefinitionMap.put ("/js/**", "anon"); filterChainndefinitionMap.put ("/login", "anon"); // Aqui, defina a página de logout como anon, não logout, porque o logout é processado por um único ponto e não precisa ser interceptado pelo Filtrofilter de Shiro FilterChainitionMap.put ("/logout", "anon"); filterChainndefinitionMap.put ("/erro", "anon"); // 3. Solicitações interceptadas (obtenha do banco de dados local ou do caçarista (métodos remotos como WebService, HTTP, etc.), veja onde sua função permite configurada) FilterChainDefinitionMap.put ("/User", "authc"); // Login necessário // 4. O login não intercepta filterChainndefinitionMap.put ("/**", "authc"); shirofilterFactoryBean.SetFilterChaindEfinitionMap (FilterChaIndEfinitionMap); }}Alguma referência de configuração: http://shiro.apache.org/spring.html
3. Escreva o reino
Como precisamos integrar as funções do sinal único, precisamos integrar a classe Casrealm. Esta classe implementou as funções da autenticação de ponto único para nós. O que precisamos fazer é implementar as funções da parte da autorização. O código de exemplo é o seguinte:
pacote com.chhliu.springboot.shiro.config; importar javax.annotation.resource; importar org.apache.shiro.securityutils; importar org.apache.shiro.authc.authenticationInfo; importar org.apache.shiro.authc.authenticationToken; importar org.apache.shiro.authz.authenticationInfo; importar org.apache.shiro.authz.simpleAuthorizationInfo; importar org.apache.shiro.cas.casrealm; importar org.apache.shiro.subject.principalCollection; importar com.chhliu.springboot.shiro.mode.syspermission; importar com.chhliu.springboot.shiro.mode.syspermission; importar com.chhliu.springboot.shiro.mode.userinfo; importar com.chhliu.springboot.shiro.service.userinfoservice; /*** Classe do núcleo de verificação de permissão; Como o sinal único é usado, não há necessidade de autenticar, apenas a autorização é necessária * * @author chhliu */ public classe myshirorealm estende o casrealm {@resource userInfoservice userInfoservice; / *** 1. Autenticação CAS, verifique a identidade do usuário* 2. Defina as informações básicas do usuário na sessão para facilitar o acesso* 3. Este método pode usar diretamente o método de autenticação no CasRealm, que é usado apenas como um teste*/ @Override AuthenticationInfo DogETAthenticationInfo (AuthenticationToken Token) {/ Casrealm implementou um único ponto de autenticação para nós. AuthenticationInfo authc = super.DogEtauthenticationInfo (token); // Obtenha a conta logada. Depois que a autenticação CAS for bem -sucedida, a conta será salva. String conta = (string) authc.getPrincipals (). GetPrimaryPrincipal (); // Salve as informações do usuário na sessão para facilitar a aquisição do programa. Aqui você pode colocar as informações do usuário consultadas com base na conta de login na sessão SecurityUtils.getSubject (). GetSession (). SetAttribute ("não", conta); retornar authc; } /*** O retorno de chamada será executado apenas quando esse método chamar o hasrole e a haspermission. * * Informações de permissão. (Autorização): 1. Se o usuário sair normalmente, o cache será limpo automaticamente; 2. Se o usuário sair de forma anormal, o cache será limpo automaticamente; * 3. Se modificarmos as permissões do usuário, mas o usuário não registrará o sistema, as permissões modificadas não podem entrar em vigor imediatamente. (Ele precisa ser implementado manualmente; colocar em serviço para chamada) * Após a permissão ser modificada, o método no reino é chamado. O reino foi gerenciado pela primavera, para que a instância do reino seja obtida na primavera e o método nítido é chamado; *: Autorização é um controle de acesso autorizado, usado para autorizar a operação realizada pelo usuário, provando se o usuário permite a operação atual, como acessar um determinado link, um determinado arquivo de recursos, etc. * * @param princípios * @return */ @Override AuthorizationInfo DogETAuthorizationInFo (Principais Principais). Configuração-> myshiroreal.DogEtauthorizationInfo () "); SimpleAuthorizationInfo AuthorizationInfo = new SimpleAuthorizationInfo (); // Obtenha o nome de usuário Após a entrada única, você também pode obtê-lo da sessão, porque após a autenticação ser bem-sucedida, o nome de usuário foi colocado na sessão String UserName = (String) super.getAvailablePrincipal (diretores); // Principais.getPrimaryPrincipal (); Este método também pode obter o nome do usuário // obter a função e as informações de permissão do usuário com base no nome do usuário userInfo userInfo = userInfoservice.findbyusername (nome de usuário); // Pacote a função correspondente do usuário e as informações de permissão no autorizaçãoInfo para (função sysrole: userinfo.getRolelist ()) {AuthorizationInfo.addrole (role.getRole ()); for (syspermission p: role.getPermissions ()) {AuthorizationInfo.addstringPermission (p.getPermission ()); }} retornar autorizaçãoInfo; }} Em seguida, podemos realizar testes de verificação!
Digite HTTP: 127.0.1.28: 8080/userinfo/userlist no navegador e descobriremos que ele irá automaticamente pular para a página de login de ponto único
Em seguida, inserimos o nome de usuário e a senha e ele irá automaticamente para a página HTTP: 127.0.1.28: 8080/userInfo/userlist.
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.