ApplicationCode:应用代码,程序员自己编写
Subject:shiro框架提供接口,代表当前“用户”,subject对象有状态;理解:subject包含自定义User对象
Shiro SecurityManager:核心,安全管理器;管理所有用户
Realm:框架提供一些,一般自己编写。通过realm调用dao查询安全数据(用户名密码;用户的权限,角色)
开始认证(登陆)
完善userAction中登陆:applicationCode --->Subject----->securityManager------->自定义realm
完善realm中认证方法:
基于shiro的url拦截方式权限控制
在realm中授权
applicationContext.xml
<!-- 配置shiro 过滤器工厂对象 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 注入安全管理器 -->
<property name="securityManager" ref="securityManager"></property>
<!-- private String loginUrl; 当后边配置url,需要当前用户认证通过后才可以访问;如果用户没有登陆,跳转登陆页面
private String successUrl; 权限不足页面
private String unauthorizedUrl; -->
<property name="loginUrl" value="/login.jsp"></property>
<property name="unauthorizedUrl" value="/unauthorized.jsp"></property>
<!-- 注入过滤器链:配置系统中url请求拦截规则 注意:配置url拦截规则有顺序
authc:过滤器工厂产生过滤器之一
/**:所有请求
当系统发送某url要求当前用户必须认证通过后才能访问
anon:匿名过滤器:访问url不需要当前用户认证,没有权限可以访问
perms:权限过滤器:访问url需要当前用户具有某个权限才可以访问
-->
<property name="filterChainDefinitions">
<value>
/login.jsp = anon
/css/** = anon
/js/** = anon
/images/** = anon
/validatecode.jsp* = anon
/userAction_login.action = anon
/pages/base/standard.jsp = perms["standard_page"]
/** = authc
</value>
</property>
</bean>
<!-- 配置安全管理器对象 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="bosRealm"></property>
</bean>
<!-- 配置realm对象 -->
<bean id="bosRealm" class="com.itheima.bos.realm.BosRealm"></bean>
<!-- spring提供配置shiro注解扫描
在servie层方法上使用shiro注解,运行时期此方法所在类产生代理对象
AutoProxy:自动代理,根据请求自动选择代理技术
jdk动态代理:基于接口
cglib动态代理:基于Class
注意:强制使用cglib动态代理
-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
<property name="proxyTargetClass" value="true"></property>
</bean>
<!-- 配置shiro的切面:(切点+通知/增强) 增强:验证当前用户是否有权限 -->
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"></bean>
public class UserAction extends BaseAction<User> { @Autowired private UserService userService; //接收验证码 private String checkCode; public void setCheckCode(String checkCode) { this.checkCode = checkCode; } /** * @Description: 基于shiro实现登陆(认证) * @return * @throws Exception * */ @Action("userAction_login") public String login() throws Exception { if(StringUtils.isNotBlank(model.getUsername())&& StringUtils.isNoneBlank(model.getPassword())&&StringUtils.isNotBlank(checkCode)){ //判断验证码 String realCheckCode = (String) ServletActionContext.getRequest().getSession().getAttribute("key"); if(checkCode.equals(realCheckCode)){ //相等,开始通过shiro实现认证 //通过工具类获取subject对象 Subject subject = SecurityUtils.getSubject(); //当前“用户”,未认证状态 //创建认证令牌; 封装页面提交用户名,密码 AuthenticationToken token = new UsernamePasswordToken(model.getUsername(), Md5Util.encode(model.getPassword()));; //logion方法调用安全管理器; try { subject.login(token); } catch (Exception e) { e.printStackTrace(); //认证失败 return "login"; } //认证通过 //从主角中获取用户信息,将用户的信息存Session中 User user = (User) subject.getPrincipal(); ServletActionContext.getRequest().getSession().setAttribute("loginUser", user); return "index"; } }else{ return "login"; } return super.execute(); } }
public class BosRealm extends AuthorizingRealm{ @Autowired private UserDao userDao; /** * @Description: * @param token subject.login方法中传 用户名密码令牌 * @return */ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("开始认证"); UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token; //页面输入的用户名 //根据用户名查询数据库中真实密码 String username = usernamePasswordToken.getUsername(); User user = userDao.findByUsername(username); if(user==null){ //用户名输出错误 return null; //当此方法中返回null,shiro会抛出异常 :未知账户异常 } //比对密码工作交给shiro框架 //p1:主角 p2:令牌/真实密码 p3:当前realm名称 AuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), this.getName()); return info; } //授权 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { System.out.println("开始授权"); //TODO 后期改造查询数据库中对应的权限,角色 //返回简单授权信息:包含当前用户有的权限点;角色 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //添加用户权限 info.addStringPermission("standard_page"); info.addStringPermission("courier_delete"); //添加用户角色 info.addRole("admin"); return info; } }