当在Spring应用中需要使用安全、身份验证等功能时,可以使用Apache Shiro安全框架。下面是在Spring应用中集成Apache Shiro的方法:
第一步:导入相关依赖
在pom.xml文件中,加入Shiro和Spring集成的依赖:
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.7.0</version>
</dependency>
<!--Spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
第二步:配置shiro.ini
在src/main/resource目录下,新建一个shiro.ini文件,这个文件是Shiro的配置文件,通过配置这个文件来定义Shiro的安全管理器、realm等。
[main]
# 定义 Shiro 的安全管理器
securityManager = org.apache.shiro.web.mgt.DefaultWebSecurityManager
# 定义 Realm
realm = org.apache.shiro.realm.jdbc.JdbcRealm
realm.authenticationQuery = SELECT password FROM users WHERE username = ?
realm.userRolesQuery = SELECT role FROM user_roles WHERE username = ?
realm.permissionsQuery = SELECT permission FROM roles_permissions WHERE role = ?
# 注册 Realm
securityManager.realms = $realm
# 配置记住我功能的 Cookie
cookie = org.apache.shiro.web.servlet.SimpleCookie
cookie.name = rememberMe
cookie.maxAge = 2592000
# 配置会话管理器
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
sessionManager.globalSessionTimeout = 1800000
sessionManager.deleteInvalidSessions = true
sessionManager.sessionValidationSchedulerEnabled = true
# 配置缓存管理
cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
cacheManager.cacheManagerConfigFile = classpath:ehcache.xml
# 将 securityManager 交由 Spring 管理
securityManager.sessionManager = $sessionManager
securityManager.cacheManager = $cacheManager
WebSecurityManager = $securityManager
[users]
admin = 123456,admin
guest = 123456,guest
[roles]
admin = *
guest = user:query
[urls]
/login.jsp = anon
/logout.jsp = logout
/** = authc
第三步:使用Shiro的FilterChain
在Spring的xml文件中定义Shiro的Filter,如下:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="WebSecurityManager"/>
<property name="loginUrl" value="/login.html"/>
<property name="successUrl" value="/index.html"/>
<property name="unauthorizedUrl" value="/error.html"/>
<property name="filterChainDefinitionMap">
<map>
<entry key="/login.html" value="anon"></entry>
<entry key="/logout.html" value="logout"></entry>
<entry key="/**" value="authc"></entry>
</map>
</property>
</bean>
在这个配置中,我们定义了ShiroFilter的Bean,并注入了刚刚定义的WebSecurityManager作为其安全管理器。同时,我们定义了3个属性,分别对应登录的URL、登录成功后的URL、未授权时的URL。
最后我们定义了Url和filterChain的对应关系,通俗点来说就是定义了哪些URL需要进行过滤,哪些不需要过滤。
示例一:基于注解
@Service
public class UserServiceImpl implements UserService {
@RequiresAuthentication
@Override
public void add(User user) {
userDao.add(user);
}
@RequiresAuthentication
@Override
public void delete(User user) {
userDao.delete(user);
}
@RequiresRoles("admin")
@Override
public void update(User user) {
userDao.update(user);
}
@RequiresPermissions("user:query")
@Override
public List<User> query(User user) {
return userDao.query(user);
}
}
在这个示例中,我们在Service的实现类中使用到了Shiro的注解功能,对每个方法进行了不同的权限、角色、权限的要求。通过这种方式,我们可以在不需要进行大量手动编写拦截的情况下进行对方法的权限限制。当然,在使用这个功能时,需要在xml中做如下的配置:
<!-- 开启 Shiro 注解支持 -->
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="WebSecurityManager"/>
</bean>
<!-- 开启 AOP 代理 -->
<aop:config proxy-target-class="true"/>
<aop:advisor advice-ref="authorizationAttributeSourceAdvisor"
pointcut="@annotation(org.apache.shiro.authz.annotation.RequiresAuthentication) or
@annotation(org.apache.shiro.authz.annotation.RequiresPermissions) or
@annotation(org.apache.shiro.authz.annotation.RequiresRoles)"/>
其中,定义了一个authorizationAttributeSourceAdvisor,作为一个advisor的配置,指定了三个切入点,分别对应了Shiro的三个注解。这样,当使用到了Shiro注解时,就可以在方法执行之前先判断用户是否满足对应的角色、权限、身份了。
示例二:自定义Realm
public class MyRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo authInfo = new SimpleAuthorizationInfo();
String username = (String) principals.getPrimaryPrincipal();
User user = userService.getUserByName(username);
if (user != null) {
List<Role> roles = user.getRoles();
if (roles != null) {
for (Role role : roles) {
authInfo.addRole(role.getName());
List<Permission> permissions = role.getPermissions();
if (permissions != null) {
for (Permission permission : permissions) {
authInfo.addStringPermission(permission.getName());
}
}
}
}
}
return authInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
String username = upToken.getUsername();
User user = userService.getUserByName(username);
if (user == null) {
throw new UnknownAccountException("用户名不存在");
}
SimpleAuthenticationInfo authInfo =
new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());
return authInfo;
}
}
这个示例中,我们自定义了一个Realm,并继承了AuthorizingRealm。在这个Realm中,我们指定了验证身份和权限的方法,同时注入了UserService,通过它来获取用户、角色、权限等信息。
最后,在xml中我们需要做如下的配置:
<!-- 注册自定义的 Realm -->
<bean id="myRealm" class="com.example.MyRealm">
<property name="permissionResolver" ref="myPermissionResolver"/>
<property name="credentialsMatcher" ref="myCredentialsMatcher"/>
</bean>
<!-- 配置 RememberMeCookie -->
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="rememberMe"/>
<property name="maxAge" value="2592000"/>
</bean>
<!-- 配置 RememberMeManager -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<property name="cookie" ref="rememberMeCookie"/>
</bean>
<!-- 配置 RememberMeConfig -->
<bean id="rememberMeConfig" class="org.apache.shiro.web.config.RememberMeConfig">
<property name="rememberMeEnabled" value="true"/>
<property name="rememberMeManager" ref="rememberMeManager"/>
</bean>
<!-- 配置 SecurityManager -->
<bean id="webSecurityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
<property name="sessionManager" ref="sessionManager"/>
<property name="cacheManager" ref="cacheManager"/>
<property name="rememberMeManager" ref="rememberMeManager"/>
</bean>
在这个配置中,我们定义了自定义的Realm,并将其注入到了WebSecurityManager中。同时,还为了方便记住密码的功能,定义了RememberMeCookie、RememberMeManager、RememberMeConfig,并在WebSecurityManager中注入了RememberMeManager。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring 应用中集成 Apache Shiro的方法 - Python技术站