一、shiro认证
1、请求认证
Subject subject = SecurityUtils.getSubject();// 根据运行环境返回subject
subject.login(token);// 这里的token一般指的是 UsernamePasswordToken,参数有
// String username, String password, boolean rememberMe, String host ,有多种构造函数
2、通过SecurityManager执行认证
public void login(AuthenticationToken token) throws AuthenticationException {
this.clearRunAsIdentitiesInternal();
Subject subject = this.securityManager.login(this, token);// 调用securityManager
String host = null;
PrincipalCollection principals;
if (subject instanceof DelegatingSubject) {
DelegatingSubject delegating = (DelegatingSubject)subject;
principals = delegating.principals;
host = delegating.host;
} else {
principals = subject.getPrincipals();
}// 无论怎么样principals = subject.getPrincipals();既用户名
if (principals != null && !principals.isEmpty()) {
this.principals = principals;
this.authenticated = true;
if (token instanceof HostAuthenticationToken) {
host = ((HostAuthenticationToken)token).getHost();
}
if (host != null) {
this.host = host;
}
Session session = subject.getSession(false);
if (session != null) {
this.session = this.decorate(session);
} else {
this.session = null;
}
} else {
String msg = "Principals returned from securityManager.login( token ) returned a null or empty value. This value must be non null and populated with one or more elements.";
throw new IllegalStateException(msg);
}
}
3、SecurityManager通过ModularRealmAuthenticator再通过realm进行认证
在自定义的Realm中完成认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获取用户的输入的账号.
String username = (String) token.getPrincipal();
User user = userService.selectByUsername(username);
String password = user.getPassword();
if (user == null) throw new UnknownAccountException();
if (0 == user.getEnable()) {
throw new LockedAccountException(); // 帐号锁定
}
//通过这个进行认证,并返回
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, password, null, getName());
Session session = SecurityUtils.getSubject().getSession();// 当验证都通过后,把用户信息放在session里
session.setAttribute("userSession", user);
session.setAttribute("userSessionId", user.getId());
return simpleAuthenticationInfo;
}
4、认证的配置
这些配置在shiro的配置文件中完成
@Bean
public MyShiroRealm myShiroRealm() {
MyShiroRealm myShiroRealm = new MyShiroRealm();
myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());// 凭证验证器
return myShiroRealm;
}
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher() {// 凭证验证器
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
hashedCredentialsMatcher.setHashIterations(1);//散列的次数,比如散列两次,相当于 md5(md5(""));
return hashedCredentialsMatcher;
}
二、shiro授权
1、ModularRealmAuthenticator通过realm进行认证
在自定义的Realm中完成授权,将用户的权限查出,配置到info中去。
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String username = (String) principalCollection.getPrimaryPrincipal();
User user = userService.selectByUsername(username);
Map<String, Object> map = new HashMap();
map.put("userid", user.getId());
List<Resources> resourcesList = resourcesService.loadUserResources(map);
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); // 权限信息对象info
for (Resources resources : resourcesList) {
info.addStringPermission(resources.getResurl()); // 在这里存放查出的用户的所有的角色(role)及权限(permission)
}
return info;
}
2、授权的配置,通过filterChainDefinitionMap在Shiro的拦截器中配置
这些配置在shiro的配置文件中完成
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setSuccessUrl("/usersPage");// 登录成功跳转的页
shiroFilterFactoryBean.setUnauthorizedUrl("/403");// 未授权界面;
Map<String, String> filterChainDefinitionMap = new LinkedHashMap();
filterChainDefinitionMap.put("/logout", "logout");// 配置登出地址,不需要专门去写控制器
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
filterChainDefinitionMap.put("/font-awesome/**", "anon");// 首先放过一般的静态资源
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); // 配置所有需要拦截的地址
return shiroFilterFactoryBean;
}
2.1配置规则
// 将需要配置的地址放入map中,规则如下:
/**
anon:例子/admins/**=anon 没有参数,表示可以匿名使用。
authc:例如/admins/user/**=authc表示需要认证(登录)才能使用,没有参数
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没有参数表示必须存在用户,当登入操作时不做检查
*/
// 详情参考shiro.web.filter源码
三、shiro认证
在shiro的配置文件中加入
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
html中加入xmlns
<html lang="zh_CN" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
maven依赖
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>1.2.1</version>
</dependency>