shiro如何使用详解
一.Shiro能做什么。
Shiro 可以帮助我们完成:认证、授权、加密、会话管理、与 Web 集成、缓存等。这不就是我们想要的嘛,而且 Shiro 的 API 也是非常简单
(注意:记住一点,Shiro 不会去维护用户、维护权限;这些需要我们自己去设计 / 提供;然后通过相应的接口注入给 Shiro 即可)
二.Shiro使用步骤。
1.先把账号密码传入Shiro里面的UsernamePasswordToken对象里面。
UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
2.创建Subject对象。
Subject subject = SecurityUtils.getSubject();
3.调用 Subject.login()进行登录,如果失败将得到相应的 AuthenticationException 异常,根据异常提示用户错误信息;否则登录成功。
try{
Subject.login(token)//调用安全管理器,安全管理器调用自定义Realm
User user = (User) subject.getPrincipal();//登陆成功后就可以通过安全管理器获得用户对象。
}catch (UnknownAccountException e) {
error = "用户名/密码错误";
} catch (IncorrectCredentialsException e) {
error = "用户名/密码错误";
} catch (ExcessiveAttemptsException e) {
// TODO: handle exception
error = "登录失败多次,账户锁定10分钟";
} catch (AuthenticationException e) {
// 其他错误,比如锁定,如果想单独处理请单独catch处理
error = "其他错误:" + e.getMessage();
}
if (error != null) {// 出错了,返回登录页面
request.setAttribute("error", error);
return "failure";
} else {// 登录成功
return "success";
}
4.最后调用 Subject.logout 进行退出操作
5.自定义Realm去写登陆的判断
public class UserRealm extends AuthorizingRealm {
private UserService userService = new UserServiceImpl();
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {//用户授权
String username = (String)principals.getPrimaryPrincipal();//获取用户名
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
authorizationInfo.setRoles(userService.findRoles(username));
authorizationInfo.setStringPermissions(userService.findPermissions(username));//根据用户名查询权限集合
return authorizationInfo;
}
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//用户认证
String username = (String)token.getPrincipal();
User user = userService.findByUsername(username);
if(user == null) {
throw new UnknownAccountException();//没找到帐号
}
if(Boolean.TRUE.equals(user.getLocked())) {
throw new LockedAccountException(); //帐号锁定
}
//交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以在此判断或自定义实现
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user.getUsername(), //用户名
user.getPassword(), //密码
ByteSource.Util.bytes(user.getCredentialsSalt()),//salt=username+salt
this.getClass().getName() //realm name
);
return authenticationInfo;
}
}
三.Shiro加解密。
1.加密。
public static void main(String[] args) {
String algorithmName = "md5"; //用什么来加密
String username = "wang";
String password = "111111";
String salt1 = username;
String salt2 = new SecureRandomNumberGenerator().nextBytes().toHex(); //shiro自带的生成随机数
int hashIterations = 3; //加密几回
SimpleHash hash = new SimpleHash(algorithmName, password, salt1 + salt2, hashIterations);
String encodedPassword = hash.toHex(); //把加密后的对象转换成字符串
System.out.println(encodedPassword);
System.out.println(salt2); //一般把加的盐保存在数据表中
}
2.解密。
首先要在sping.xml文件里面配置
<!-- 凭证匹配器 -->
<bean id="credentialsMatcher" class="com.firstelite.cq.util.RetryLimitHashedCredentialsMatcher">
<constructor-arg ref="cacheManager" />
<property name="hashAlgorithmName" value="md5" />//指定解密的编码方式
<property name="hashIterations" value="3" /> //解密几次MD5
<property name="storedCredentialsHexEncoded" value="true" />
</bean>
然后
public String getCredentialsSalt() {
return username + salt;
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user.getUsername(), // 用户名
user.getPassword(), // 密码
ByteSource.Util.bytes(user.getCredentialsSalt()),// salt=username+salt
this.getClass().getName() // realm name
);
四.shiro的权限控制
1.首先在在springmvc.xml配置
<!-- 开启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>
Shiro 可以帮助我们完成:认证、授权、加密、会话管理、与 Web 集成、缓存等。这不就是我们想要的嘛,而且 Shiro 的 API 也是非常简单
(注意:记住一点,Shiro 不会去维护用户、维护权限;这些需要我们自己去设计 / 提供;然后通过相应的接口注入给 Shiro 即可)
二.Shiro使用步骤。
1.先把账号密码传入Shiro里面的UsernamePasswordToken对象里面。
UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
2.创建Subject对象。
Subject subject = SecurityUtils.getSubject();
3.调用 Subject.login()进行登录,如果失败将得到相应的 AuthenticationException 异常,根据异常提示用户错误信息;否则登录成功。
try{
Subject.login(token)//调用安全管理器,安全管理器调用自定义Realm
User user = (User) subject.getPrincipal();//登陆成功后就可以通过安全管理器获得用户对象。
}catch (UnknownAccountException e) {
error = "用户名/密码错误";
} catch (IncorrectCredentialsException e) {
error = "用户名/密码错误";
} catch (ExcessiveAttemptsException e) {
// TODO: handle exception
error = "登录失败多次,账户锁定10分钟";
} catch (AuthenticationException e) {
// 其他错误,比如锁定,如果想单独处理请单独catch处理
error = "其他错误:" + e.getMessage();
}
if (error != null) {// 出错了,返回登录页面
request.setAttribute("error", error);
return "failure";
} else {// 登录成功
return "success";
}
4.最后调用 Subject.logout 进行退出操作
5.自定义Realm去写登陆的判断
public class UserRealm extends AuthorizingRealm {
private UserService userService = new UserServiceImpl();
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {//用户授权
String username = (String)principals.getPrimaryPrincipal();//获取用户名
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
authorizationInfo.setRoles(userService.findRoles(username));
authorizationInfo.setStringPermissions(userService.findPermissions(username));//根据用户名查询权限集合
return authorizationInfo;
}
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//用户认证
String username = (String)token.getPrincipal();
User user = userService.findByUsername(username);
if(user == null) {
throw new UnknownAccountException();//没找到帐号
}
if(Boolean.TRUE.equals(user.getLocked())) {
throw new LockedAccountException(); //帐号锁定
}
//交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以在此判断或自定义实现
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user.getUsername(), //用户名
user.getPassword(), //密码
ByteSource.Util.bytes(user.getCredentialsSalt()),//salt=username+salt
this.getClass().getName() //realm name
);
return authenticationInfo;
}
}
三.Shiro加解密。
1.加密。
public static void main(String[] args) {
String algorithmName = "md5"; //用什么来加密
String username = "wang";
String password = "111111";
String salt1 = username;
String salt2 = new SecureRandomNumberGenerator().nextBytes().toHex(); //shiro自带的生成随机数
int hashIterations = 3; //加密几回
SimpleHash hash = new SimpleHash(algorithmName, password, salt1 + salt2, hashIterations);
String encodedPassword = hash.toHex(); //把加密后的对象转换成字符串
System.out.println(encodedPassword);
System.out.println(salt2); //一般把加的盐保存在数据表中
}
2.解密。
首先要在sping.xml文件里面配置
<!-- 凭证匹配器 -->
<bean id="credentialsMatcher" class="com.firstelite.cq.util.RetryLimitHashedCredentialsMatcher">
<constructor-arg ref="cacheManager" />
<property name="hashAlgorithmName" value="md5" />//指定解密的编码方式
<property name="hashIterations" value="3" /> //解密几次MD5
<property name="storedCredentialsHexEncoded" value="true" />
</bean>
然后
public String getCredentialsSalt() {
return username + salt;
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user.getUsername(), // 用户名
user.getPassword(), // 密码
ByteSource.Util.bytes(user.getCredentialsSalt()),// salt=username+salt
this.getClass().getName() // realm name
);
四.shiro的权限控制
1.首先在在springmvc.xml配置
<!-- 开启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>
2.再在controller里配置注解
3.jsp里shiro标签