shiro简介
ApacheShiro是一个强大而灵活的开源安全框架,它能够干净利落地处理身份认证,授权,企业会话管理和加密(核心功能)。
以下是你可以用ApacheShiro所做的事情:
1.验证用户
2.对用户执行访问控制,如:
判断用户是否拥有角色admin。
判断用户是否拥有访问的权限
3.在任何环境下使用SessionAPI。例如CS程序。
4.可以使用多个用户数据源。例如一个是oracle用户库,另外一个是mysql用户库。
5.单点登录(SSO)功能。
6.“RememberMe”服务,类似购物车的功能,shiro官方建议开启
shiro框架执行流程
ApplicationCode:应用程序代码,由开发人员负责开发
subject:主体,当前用户
securitymanager:安全管理器,框架的核心,负责调用realm,框架提供
realm:类似于dao,访问安全数据(权限、角色、用户),框架提供,也可以自定义
权限控制方式:
方式一:URL拦截方式
第一步:导包
第二步:在web.xml里面配置由spring框架提供整合shero的过滤器
1
2
3
4
5
6
7
8
9
10
11
12
13
3ff0
14
15
16
17
18
19
| <!--指定spring配置文件-->
< context-param >
< param-name >contextConfigLocation</ param-name >
< param-value >classpath:applicationContext.xml</ param-value >
</ context-param >
< listener >
< listener-class >org.springframework.web.context.ContextLoaderListener</ listener-class >
</ listener >
<!--配置权限管理-->
< filter >
< filter-name >shiroFilter</ filter-name >
< filter-class >org.springframework.web.filter.DelegatingFilterProxy</ filter-class >
</ filter >
< filter-mapping >
< filter-name >shiroFilter</ filter-name >
< url-pattern >/*</ url-pattern >
</ filter-mapping >
|
第三步:在applicationContext.xml里面配置一个bean,并且id要和过滤器的名字一样
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| <!--第一种代码配置设置shiro权限-->
< bean id = "shiroFilter" class = "org.apache.shiro.spring.web.ShiroFilterFactoryBean" >
< property name = "securityManager" ref = "securityManager" ></ property >
< property name = "loginUrl" value = "/login.jsp" ></ property >
< property name = "successUrl" value = "/index.jsp" ></ property >
< property name = "unauthorizedUrl" value = "/500.jsp" ></ property >
< property name = "filterChainDefinitions" >
< value >
/css/**=anon
/js/**=anon
/images/**=anon
/login.jsp*=anon
/validatecode.jsp*=anon
/UserAction_login.action*=anon
/page_base_staff.action=perms["staff"]
/**=authc
</ value >
</ property >
</ bean >
|
第四步:在applicationConte.xml里面配置安全管理器,并且注入Realm
1
2
3
4
5
| < bean id = "securityManager" class = "org.apache.shiro.web.mgt.DefaultWebSecurityManager" >
< property name = "realms" ref = "shiroRealms" ></ property >
< property name = "cacheManager" ref = "cache" ></ property >
</ bean >
< bean id = "shiroRealms" class = "com.mickeymouse.bos.shiro.ShiroRealms" ></ bean >
|
第五步:编写一个realm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
3ff0
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
| package com.mickeymouse.bos.shiro;
import java.util.List;
import javax.annotation.Resource;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import com.mickeymouse.bos.dao.IFunctionDao;
import com.mickeymouse.bos.dao.IUserDao;
import com.mickeymouse.bos.domain.Function;
import com.mickeymouse.bos.domain.User;
public class ShiroRealms extends AuthorizingRealm{
@Autowired
private IUserDaoiUserDao;
@Resource
private IFunctionDaoiFunctionDao;
/**
*授权
*/
@Override
protected AuthorizationInfodoGetAuthorizationInfo(
PrincipalCollectionprincipals){
//获取认证信息
SimpleAuthorizationInfoauthorizationInfo= new SimpleAuthorizationInfo();
//通过认证信息获取当前用户
Useruser=(User)principals.getPrimaryPrincipal();
//先判断是不是超管
if (user.getUsername()== "admin" ){
//超管:直接查询所有权限
List<Function>list=iFunctionDao.findAll();
for (Function function :list){
authorizationInfo.addStringPermission( function .getCode());
}
} else {
//普通用户:通过用户ID查询所具有的权限
List<Function>list=iFunctionDao.findFunctionByUserid(user.getId());
for (Function function :list){
authorizationInfo.addStringPermission( function .getCode());
}
}
return authorizationInfo;
}
/**
*认证:判断用户名与密码是否正确
*/
@Override
protected AuthenticationInfodoGetAuthenticationInfo(
AuthenticationTokentoken)throwsAuthenticationException{
//通过认证标记获取传入的用户名
UsernamePasswordTokenusernamePasswordToken=(UsernamePasswordToken)token;
String username=usernamePasswordToken.getUsername();
//通过用户名查询数据库返回对象
Useruser=iUserDao.findByUserFronUsername(username);
if (user== null ){
//如果为空直接返回null,此时subject会直接抛出异常
return null ;
} else {
//账号存在,将从数据库中查询出的密码交给安全管理器比对
//三个参数:第一个验证正确后需要的返回值,第二个:安全管理器需要的比对密码,第三个:realm的类名
//简单认证信息对象
AuthenticationInfoauthenticationInfo= new SimpleAuthenticationInfo(user,user.getPassword(), this .getName());
return authenticationInfo;
}
}
}
|
第六步:使用shero框架完成登录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| /**
*登录
*@return
*/
public String login(){
String key=( String )ActionContext.getContext().getSession(). get ( "key" );
//取出用户名密码为空
if (!StringUtils.isEmpty(t.getUsername())&&!StringUtils.isEmpty(t.getPassword())){
//去除验证码错误或空
if (!StringUtils.isEmpty(checkcode)&&!StringUtils.isEmpty(key)&&key.equals(checkcode)){
//获取当前用户,此时的状态为"未认证"
Subjectsubject=SecurityUtils.getSubject();
//创建用户名和密码的认证标记
AuthenticationTokenauthenticationToken= new UsernamePasswordToken(t.getUsername(),MD5Utils.md5(t.getPassword()));
try {
//调用登录方法,传入认证标记
subject.login(authenticationToken);
//如果没有异常,那么返回"认证信息传出的返回值对象"
Useruser=(User)subject.getPrincipal();
//存入session域中
ActionContext.getContext().getSession().put( "User" ,user);
return "home" ;
} catch (Exceptione){
e.printStackTrace();
this .addActionMessage( "用户名或者密码不正确~" );
}
} else {
this .addActionMessage( "验证码错误!" );
}
} else {
this .addActionMessage( "用户名或者密码不能为空!" );
}
return "login" ;
}
|
异常信息:
当用户名错误,认证信息为空抛出异常
当密码错误,安全管理器抛出异常
方式二:注解方式
第一步:导包
第二步:在applicationContext.xml里开启shero注解
1
2
3
4
5
6
| <!--第二种:注解方式设置shiro权限-->
<!-- 1 .开启shiro注解-->
<beanid= "defaultAdvisorAutoProxyCreator" class = "org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" >
<propertyname= "proxyTargetClass" value= "true" ></property>
</bean>
<bean class = "org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor" ></bean>
|
第三步:在Action的方法上使用shiro注解描述需要具有的权限
1
2
3
4
5
6
7
8
9
10
11
| /**
*分页查询
*/
@RequiresPermissions (value= "region" ) //执行这个方法需要具有region.query这个权限
@RequiresRoles (value= "admin" )
public StringpageQuery(){
regionService.pageQuery(pageBean);
String[]excludes= new String[]{ "subareas" };
this .writePageBean2Json(pageBean,excludes);
return NONE;
}
|
第四步:注意修改action抽取类的构造方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| public ActionBase(){
ParameterizedTypeparameterizedType= null ;
TypegenericSuperclass= this .getClass().getGenericSuperclass();
&n 3ff0 bsp; if (genericSuperclass instanceof ParameterizedType){
parameterizedType=(ParameterizedType) this .getClass().getGenericSuperclass();
} else {
//这里的this为shero的代理对象
parameterizedType=(ParameterizedType) this .getClass().getSuperclass().getGenericSuperclass();
}
//获得BaseAction类定义的泛型数组
Type[]types=parameterizedType.getActualTypeArguments();
Class<T>class1=(Class<T>)types[ 0 ];
try {
t=class1.newInstance();
} catch (InstantiationExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
} catch (IllegalAccessExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
|
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理