一、前言
Apache Shiro 与 Spring Security 一样是 Java 的一个安全框架。那为什么与 Spring 整合却用 Shiro?其实我个人是认为 Spring Security 太过于笨重,要写太多的过滤器,Shiro 的配置简单这就是我选择的理由,何况 Spring 官方自己都推荐使用 Shiro。Shiro 最主要的就是认证与授权,而 CAS 的重点在于单点登录,其实 CAS 与 Shiro 整合的话就是关于认证那块的整合。
二、配置
第一步、添加 Maven 依赖
<!-- shiro 依赖包 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.4</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.3</version>
</dependency>
<!-- shiro-cas 集成依赖包 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-cas</artifactId>
<version>1.2.3</version>
</dependency>
第二步、web.xml 中添加shiro过滤器
shiroFilter
org.springframework.web.filter.DelegatingFilterProxy
targetFilterLifecycle
true
shiroFilter
/*
第三步、添加 applicationContext-shiro.xml 配置文件
<description>Shiro 配置</description>
<!-- CasFilter 为自定义的单点登录 Fileter -->
<!--shiroFilter 的 bean Name 必须与 web.xml 中 shiro filter 的名字一致-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- Shiro 的核心安全接口,这个属性是必须的 -->
<property name="securityManager" ref="securityManager"/>
<!-- 要求登录时的链接(可根据项目的 URL 进行替换),非必须的属性,默认会自动寻找 Web 工程根目录下的"/login.jsp"页面 -->
<property name="loginUrl" value="http://cas.uat.qa.nt.ctripcorp.com/caso/login?service=http://127.0.0.1:8080/springdemo/shiro-cas"/>
<property name="successUrl" value="/"/>
<!-- 用户访问未对其授权的资源时,所显示的连接 -->
<property name="unauthorizedUrl" value="/static/no-permission.jsp"/>
<!-- The 'filters' property is usually not necessary unless performing
an override, which we want to do here (make authc point to a PassthruAuthenticationFilter
instead of the default FormAuthenticationFilter: -->
<property name="filters">
<util:map>
<!-- 添加 casFilter 到 shiroFilter 整合 -->
<entry key="casFilter" value-ref="casFilter"/>
<!-- <entry key="perms">
<bean
class="com.lora.shiro.filter.MyPermissionsAuthorizationFilter" />
</entry> -->
</util:map>
</property>
<!-- 读取自定义权限内容-->
<property name="filterChainDefinitions">
<value>
/shiro-cas = casFilter
/addUser/** = authc
/show/** = authc
/login = anon
/toLogin/login = anon
/static/** = anon
/static/no-permission.jsp = anon
/greeting** = authc,perms[admin:manage]
/** = anon
<!-- /home* = roles["adminHome"] -->
</value>
</property>
</bean>
<!-- 单点登录下的配置 -->
<bean id="casRealm" class="com.lora.shiro.MyCasRealm">
<property name="defaultRoles" value="ROLE_USER"/>
<!-- cas 服务端地址前缀 -->
<property name="casServerUrlPrefix" value="http://cas.uat.qa.nt.ctripcorp.com/caso" />
<!-- 应用服务地址,用来接收 cas 服务端票据 -->
<!-- 客户端的回调地址设置,必须和上面的 shiro-cas 过滤器 casFilter 拦截的地址一致 -->
<property name="casService" value="http://127.0.0.1:8080/springdemo/shiro-cas" />
</bean>
<!-- 这里主要是设置自定义的单 Realm 应用,若有多个 Realm,可使用'realms'属性代替 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- 设置自定义 realm ref="iniRealm,mySecurityRealm" -->
<!-- <property name="realm" ref="myRealm"/> -->
<property name="realm" ref="casRealm"/>
</bean>
<!--保证实现了 Shiro 内部 lifecycle 函数的 bean 执行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- 相当于调用 SecurityUtils.setSecurityManager(securityManager) -->
<bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod"
value="org.apache.shiro.SecurityUtils.setSecurityManager" />
<property name="arguments" ref="securityManager" />
</bean>
<!-- 用于开启 Shiro Spring AOP 权限注解的支持 -->
<bean
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
第四步、 添加自定义 realm 配置的实现类 MyCasRealm
package com.lora.shiro;
import java.util.Iterator;
import java.util.Map;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cas.CasRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import com.lora.model.User;
public class MyCasRealm extends CasRealm {
/**
* 授权,获取用户的角色、权限
*/
@SuppressWarnings("rawtypes")
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
if (principals == null) {
throw new AuthorizationException("Principal 对象不能为空");
}
Iterator it = principals.fromRealm(getName()).iterator();
String username = null;
if (it.hasNext()) {
username = (String) it.next();
} else {
username = principals.toString();
}
//获取用户响应的 permission
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
if (username != null) {
// 添加一个角色,不是配置意义上的添加,而是证明该用户拥有 admin 角色
info.addRole("admin");
// 添加权限
info.addStringPermission("admin:manage");
System.out.println("已为用户赋予了[admin]角色和[admin:manage]权限");
return info;
}
return info;
}
/**
* 认证,登录验证。
*/
@SuppressWarnings("rawtypes")
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
AuthenticationInfo authenticationInfo = super
.doGetAuthenticationInfo(token);
PrincipalCollection principalCollection = authenticationInfo
.getPrincipals();
Map loginDataMap = (Map) principalCollection.asList().get(1);
String userAccount = (String) loginDataMap.get("name");
String userCode = (String) loginDataMap.get("employee");
String fullName = (String) loginDataMap.get("sn");
String department = (String) loginDataMap.get("department");
String email = (String) loginDataMap.get("mail");
User user = new User();
user.setUserCode(userCode);
user.setUserAccount(userAccount);
user.setUname(fullName);
user.setDepartment(department);
user.setEmail(email);
// 将用户保存在 SESSION 回话中
Session session = SecurityUtils.getSubject().getSession();
session.setAttribute("currentUser", user);
return authenticationInfo;
}
}
以上步骤完成,shiro 集成 cas 的步骤就完成了,实现了单点登录。
作者:疯丫头 666
来源:CSDN
原文:https://blog.csdn.net/wangli61289/article/details/79224943
版权声明:本文为博主原创文章,转载请附上博文链接!