我遇到的问题:使用shiro进行登录的时候可以选择两种方案,一种是自动生成token,一种手动生成
第一种:name=”username”,name=”password”只能写这两个(目测是这样)
表单:
<TR>
<TD>用户名:</TD>
<TD colSpan="2"><input type="text" id="usercode"
name="username" style="WIDTH: 130px" /></TD>
</TR>
<TR>
<TD>密 码:</TD>
<TD><input type="password" id="pwd" name="password" style="WIDTH: 130px" />
</TD>
</TR>
控制器:
// 登陆提交地址,和applicationContext-shiro.xml中配置的loginurl一致
@RequestMapping("login")
public String login(HttpServletRequest request) throws Exception {
// 如果登陆失败从request中获取认证异常信息,shiroLoginFailure就是shiro异常类的全限定名
String exceptionClassName = (String) request.getAttribute("shiroLoginFailure");
// 根据shiro返回的异常类路径判断,抛出指定异常信息
if (exceptionClassName != null) {
if (UnknownAccountException.class.getName().equals(exceptionClassName)) {
// 最终会抛给异常处理器
throw new CustomException("账号不存在");
} else if (IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {
throw new CustomException("用户名/密码错误");
} else if ("randomCodeError".equals(exceptionClassName)) {
throw new CustomException("验证码错误 ");
} else {
throw new Exception();// 最终在异常处理器生成未知错误
}
}
// 此方法不处理登陆成功(认证成功),shiro认证成功会自动跳转到上一个请求路径
// 登陆失败还到login页面
return "login";
}
认证:
// 用于认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// token是用户输入的
// 第一步从token中取出身份信息
String userCode = (String) token.getPrincipal();
// 第二步:根据用户输入的userCode从数据库查询
// ....
// 如果查询不到返回null
// 数据库中用户账号是zhangsansan
if (!userCode.equals("zhangsan")) {
return null;
}
// 模拟从数据库查询到密码
String password = "123";
// 如果查询到返回认证信息AuthenticationInfo
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userCode, password,this.getName());
return simpleAuthenticationInfo;
}
第二种倒是没限制
控制器:
@RequestMapping("/login")
public String login(@RequestParam("username") String username, @RequestParam("password") String password) {
Subject currentUser = SecurityUtils.getSubject();
if (!currentUser.isAuthenticated()) {
// 把用户名密码封装为UsernamePasswordToken对象
UsernamePasswordToken token = new UsernamePasswordToken(username.trim(), password.trim());
// RememberMe 记住我属性
token.setRememberMe(true);
try {
// 执行登录
currentUser.login(token);
}
// 所有认证时异常的父类.
catch (AuthenticationException ae) {
System.out.println("登录失败:" + ae.getMessage());
}
}
return "redirect:/list.jsp";
}
认证:
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// 1. 把 AuthenticationToken 转换为 UsernamePasswordToken
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
// 2. 从 UsernamePasswordToken 中来获取 username
String username = upToken.getUsername();
// 3. 调用数据库的方法, 从数据库中查询 username 对应的用户记录
System.out.println("从数据库中获取 username: " + username + " 所对应的用户信息.");
// 4. 若用户不存在, 则可以抛出 UnknownAccountException 异常
if ("unknow".equals(username)) {
throw new UnknownAccountException("用户名不存在");
}
// 5. 根据用户信息的情况, 决定是否需要抛出其他的 AuthenticationException 异常.
if ("monster".equals(username)) {
throw new LockedAccountException("用户被锁定");
}
// 6. 根据用户的情况, 来构建 AuthenticationInfo 对象并返回. 通常使用的实现类为:
// SimpleAuthenticationInfo
// 以下信息是从数据库中获取的.
// 1). principal: 认证的实体信息. 可以是 username, 也可以是数据表对应的用户的实体类对象.
Object principal = username;
// 2). credentials: 密码.
Object credentials = null;// "8e56a40e92622217019f774aa9d9afdc";
credentials = new SimpleHash("MD5", "123456", username, 1);
// 3). realmName: 当前 realm 对象的 name. 调用父类的 getName() 方法即可
String realmName = getName();
// 4). 盐值
ByteSource credentialsSalt = ByteSource.Util.bytes(username);
// SimpleAuthenticationInfo info = new
// SimpleAuthenticationInfo(principal, credentials, realmName);
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials, credentialsSalt,
realmName);
return info;
}
shiro的jar包
与其它java开源框架类似,将shiro的jar包加入项目就可以使用shiro提供的功能了。shiro-core是核心包必须选用,还提供了与web整合的shiro-web、与spring整合的shiro-spring、与任务调度quartz整合的shiro-quartz等,下边是shiro各jar包的maven坐标。
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-quartz</artifactId>
<version>1.2.3</version>
</dependency>
也可以通过引入shiro-all包括shiro所有的包:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.2.3</version>
</dependency>
shiro过滤总结
过滤器简称 对应的java类
anon org.apache.shiro.web.filter.authc.AnonymousFilter
authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter
authcBasic org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
perms org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
port org.apache.shiro.web.filter.authz.PortFilter
rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
ssl org.apache.shiro.web.filter.authz.SslFilter
user org.apache.shiro.web.filter.authc.UserFilter
logout org.apache.shiro.web.filter.authc.LogoutFilter
anon:例子/admins/**=anon 没有参数,表示可以匿名使用。
authc:例如/admins/user/**=authc表示需要认证(登录)才能使用,FormAuthenticationFilter是表单认证,没有参数
roles:例子/admins/user/**=roles[admin],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,例如admins/user/**=roles["admin,guest"],每个参数通过才算通过,相当于hasAllRoles()方法。
perms:例子/admins/user/**=perms[user:add:*],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/**=perms["user:add:*,user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。
rest:例子/admins/user/**=rest[user],根据请求的方法,相当于/admins/user/**=perms[user:method] ,其中method为post,get,delete等。
port:例子/admins/user/**=port[8081],当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString
是你访问的url里的?后面的参数。
authcBasic:例如/admins/user/**=authcBasic没有参数表示httpBasic认证
ssl:例子/admins/user/**=ssl没有参数,表示安全的url请求,协议为https
user:例如/admins/user/**=user没有参数表示必须存在用户, 身份认证通过或通过记住我认证通过的可以访问,当登入操作时不做检查
注:
anon,authcBasic,auchc,user是认证过滤器,
perms,roles,ssl,rest,port是授权过滤器
在springmvc.xml中配置shiro注解支持,可在controller方法中使用shiro注解配置权限:
<!-- 开启aop,对类代理 -->
<aop:config proxy-target-class="true"></aop:config>
<!-- 开启shiro注解支持 -->
<bean
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
或者在spring中配置:
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor" />
<bean
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>