1. 创建一个新的java应用(maven)
在pom文件中引入如下依赖:
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.0</version>
</dependency>
<!-- 日志工具 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.2</version>
</dependency>
<!-- shiro默认需要的日志工具,不添加时shiro运行失败 -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
工程结构如下图:
2. 通过配置文件的方式使用shiro
(1)在resources文件夹下新增TestShiro.ini配置文件,内容如下:
#[main]
myRealm = com.ynsh.security.shiro.DatabaseRealm
credentialsMatcher = com.ynsh.security.shiro.MyCredentialsMatcher
myRealm.credentialsMatcher = $credentialsMatcher
securityManager.realms = $myRealm
securityManager.sessionManager.globalSessionTimeout = 1800000
[users]
javass = cc,role1
[roles]
role1 = p1,p2
(2)创建自定义的realm
package com.ynsh.security.shiro;
import org.apache.shiro.authc.*;
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.apache.shiro.util.ByteSource;
import java.util.HashSet;
import java.util.Set;
public class DatabaseRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String userName = (String)getAvailablePrincipal(principalCollection);
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
Set<String> s = new HashSet<>();
s.add("p1");
info.setStringPermissions(s); //赋予权限p1
Set<String> r = new HashSet<>();
r.add("role1"); //赋予角色role1
info.setRoles(r);
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
String userName = (String)upToken.getPrincipal();
// if ("javass".equals(userName)) throw new AuthenticationException("javass用户禁止登录"); 如果想禁止某一个用户登录,可以在这里操作:判断到是这个用户时,扔出异常
//这个密码正常情况下应该是从数据库去获取
String passWord = "428729c9b80aa3198300caabb24f8a88";
//扔给credentialsMatcher去判断
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
userName, passWord, null, this.getName());
return simpleAuthenticationInfo;
}
//父类调用完doGetAuthenticationInfo会调用assertCredentialsMatch,判断密码是否相符
}
(3)创建自定义的credentialsMatcher,即密码验证器
package com.ynsh.security.shiro;
import com.ynsh.security.utils.Md5Util;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
public class MyCredentialsMatcher extends SimpleCredentialsMatcher {
@Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
UsernamePasswordToken uToken = (UsernamePasswordToken)token;
String inPassword = new String(uToken.getPassword()); //这个密码是客户提交的密码,即下面main函数中用new UsernamePasswordToken("javass","bb")提交的“bb”
//这个密码是上面realm中给出的数据库密码,也就是正确的密码:String passWord = "428729c9b80aa3198300caabb24f8a88"
String dbPassword = (String)info.getCredentials();
String encryptInPassword = Md5Util.encrypt(inPassword);
return encryptInPassword.equals(dbPassword);
}
}
(4)上面用到了一个自定义的md5Util组件:
package com.ynsh.security.utils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.crypto.hash.SimpleHash;
public class Md5Util {
public static String encrypt(String originalString){
//盐
String salt = "salt";
//散列次数
int hashIterations = 2;
Md5Hash md5Hash = new Md5Hash(originalString, salt, hashIterations);
String password_md5 = md5Hash.toString();
System.out.println(password_md5);
//第一个参数:散列算法
SimpleHash simpleHash = new SimpleHash("md5", originalString, salt, hashIterations);
System.out.println(simpleHash.toString());
return simpleHash.toString();
}
}
(5)正式开始验证,写main函数:
package com.ynsh;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class App
{
private static final Logger logger = LoggerFactory.getLogger(App.class);
public static void main( String[] args )
{
Factory<SecurityManager> f = new IniSecurityManagerFactory("classpath:TestShiro.ini");
SecurityManager s = f.getInstance();
SecurityUtils.setSecurityManager(s);
UsernamePasswordToken token = new UsernamePasswordToken("javass","bb");
token.setRememberMe(true);
Subject currentUser = SecurityUtils.getSubject();
try {
currentUser.login(token);
}catch (Exception e){
logger.error(e.getMessage());
e.printStackTrace();
}
// boolean flag = currentUser.isPermitted("p1");
boolean flag = currentUser.isAuthenticated();
System.out.println("flag == "+flag);
flag = currentUser.hasRole("role1");
logger.info("用户有角色:{}",flag);
}
}
(6)运行结果如下:
[INFO ] 2018-11-22 15:13:43,087 method:org.apache.shiro.config.IniSecurityManagerFactory.isAutoApplyRealms(IniSecurityManagerFactory.java:127)
Realms have been explicitly set on the SecurityManager instance - auto-setting of realms will not occur.
428729c9b80aa3198300caabb24f8a88
428729c9b80aa3198300caabb24f8a88
[INFO ] 2018-11-22 15:13:43,102 method:org.apache.shiro.session.mgt.AbstractValidatingSessionManager.enableSessionValidation(AbstractValidatingSessionManager.java:233)
Enabling session validation scheduler...
flag == true
[INFO ] 2018-11-22 15:13:43,147 method:com.ynsh.App.main(App.java:43)
用户有角色:true
Process finished with exit code 0
后记
TestShiro.ini中配置了[users]和[roles]其实是不起作用的,这个配置是一开始的时候为了验证shiro默认的iniRealm的时候使用的。
因为自定义了realm,可以将[users]和[roles]的内容全部删除。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。