一、pom.xml引入Shiro
可以引入Apache Shiro所有的包
org.apache.shiro shiro-all ${shiro.version}
或者是根据项目需求引入需要的jar
org.apache.shiro shiro-core ${shiro.version} org.apache.shiro shiro-web ${shiro.version} org.apache.shiro shiro-spring ${shiro.version}
二、配置web.xml,配置web应用中的Shiro Filter
注意:此配置需要配置在其他拦截器之前shiroFilter org.springframework.web.filter.DelegatingFilterProxy shiroFilter /*
三、配置applicationContext-shiro.xml
Ant风格资源地址支持3种匹配符:/login.html* = anon /user_login.action* = anon /validatecode.jsp* = anon /css/** = anon /js/** = anon /images/** = anon /services/** = anon /pages/base/courier.html* = perms[courier:list] /pages/base/area.html* = roles[base] /** = authc -->
: 匹配文件名中的一个字符
* : 匹配文件名中的任意字符
** : 匹配多层路径
Shiro中的默认过滤器
anon:例子/admins/**=anon 没有参数,表示可以匿名使用
authc:例如/admins/user/**=authc表示需要认证(登录)才能使用,没有参数注意:anon,authcBasic,auchc,user是认证过滤器,perms,roles,ssl,rest,port是授权过滤器
四、UserAction
@Namespace("/") @ParentPackage("json-default") @Controller @Scope("prototype") public class UserAction extends BaseAction{ @Action(value = "user_login", results = {@Result(name = "login", type = "redirect", location = "login.html"), @Result(type = "redirect", location = "index.html")}) public String login() { // 用户名和密码都保存在model中 // 基于shiro实现登录 Subject subject = SecurityUtils.getSubject(); AuthenticationToken authenticationToken = new UsernamePasswordToken(model.getUsername(), model.getPassword()); try { subject.login(authenticationToken); // shiro执行流程:应用程序 --- Subject --- SecurityManager --- Realm 安全数据 // 登录成功 // 用户信息保存在session return SUCCESS; } catch (Exception e) { // 登录失败 e.printStackTrace(); return LOGIN; } } @Action(value = "user_logout",results = {@Result(type = "redirect",location = "login.html")}) public String logout(){ // 基于shiro完成退出 Subject subject = SecurityUtils.getSubject(); subject.logout(); return SUCCESS; }
五、自定义Realm
// 自定义的Realm,实现安全数据链接 @Service(value = "bosRealm") public class BosRealm extends AuthorizingRealm { @Autowired private UserService userService; @Autowired private RoleService roleService; @Autowired private PermissionService permissionService; @Override // 授权... protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) { System.out.println("shiro 授权管理..."); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); // 根据当前登录用户查对应角色和权限 Subject subject = SecurityUtils.getSubject(); User user = (User) subject.getPrincipal(); // 调用业务层,查询角色 Listroles = roleService.findByUser(user); for (Role role : roles){ authorizationInfo.addRole(role.getKeyword()); } // 调用业务层,返回权限 List permissions = permissionService.findByUser(user); for (Permission permission : permissions) { authorizationInfo.addStringPermission(permission.getKeyword()); } return authorizationInfo; } @Override // 认证... protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("shiro 认证管理..."); // 转换token UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token; // 根据有用户查询用户信息 User user = userService.findByUsername(usernamePasswordToken.getUsername()); if (user == null) { // 用户名不存在 // 参数一:期望登录后,保存在Subject中信息 // 参数二:密码,如果返回为null,说明用户不存在 // 参数三:realm名称 return null; } else { // 用户名存在 // 当返回用户密码时,securityManager安全管理器,自动比较返回密码和用户输入密码是否一致 // 如果一致 登录成功,如果密码不一致 报密码错误异常 return new SimpleAuthenticationInfo(user, user.getPassword(), getName()); } } }
六、Shiro登录异常
用户名不存在:
org.apache.shiro.authc.UnknownAccountException密码不正确
org.apache.shiro.authc.IncorrectCredentialsException: Submitted credentials for token [org.apache.shiro.authc.UsernamePasswordToken - admin, rememberMe=false] did not match the expected credentials.