在学习Shiro的过程中,看了这位老哥的博客图受益良多,引用标记一下原博客:https://blog.csdn.net/weixin_36795183/article/details/79012141
Shiro基本组件及其概念:
1.最简单的入门Demo
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.SimpleAccountRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Before;
import org.junit.Test;
/**
* 最基础的Demo 用SimpleAccountRealm的方式实现
*/
public class AuthenticationTest {
SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
@Before
public void addUser() {
/**
* public void addAccount(String username, String password, String... roles) {
* Set<String> roleNames = CollectionUtils.asSet(roles);
* SimpleAccount account = new SimpleAccount(username, password, getName(), roleNames, null);
* add(account);
* }
*/
simpleAccountRealm.addAccount("Kelvin","123123","user");
}
@Test
public void testAuthentication(){
//1.构建SecurityManager环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(simpleAccountRealm);
//2.主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("Kelvin","123123");
subject.login(usernamePasswordToken);
System.out.println(subject.isAuthenticated());
//检验授权
subject.checkRole("user");
//subject.checkPermission("");
}
}
2.用ini文件定义Realm
首先定义Realm,命名为user.ini,存放在resources文件夹下
[users]
Kelvin=123123,admin
[roles]
admin=user:delete
再来上Java代码
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.SimpleAccountRealm;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Before;
import org.junit.Test;
/**
* 在ini文件内编写Realm
*/
public class IniRealmTest {
@Test
public void testAuthentication(){
//指定ini文件位置
IniRealm iniRealm = new IniRealm("classpath:user.ini");
//1.构建SecurityManager环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(iniRealm);
//2.主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("Kelvin","123123");
subject.login(usernamePasswordToken);
//检验是否认证
System.out.println(subject.isAuthenticated());
//检验授权
subject.checkRole("admin");
subject.checkPermission("user:delete");
}
}
3.JDBCRealm
首先在pom导入相关的包:数据库连接包跟数据源
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.6</version>
</dependency>
我们再来看看JDBCRealm类给我们提供的缺省方法:
/**
* The default query used to retrieve account data for the user.
*/
protected static final String DEFAULT_AUTHENTICATION_QUERY = "select password from users where username = ?";
/**
* The default query used to retrieve account data for the user when {@link #saltStyle} is COLUMN.
*/
protected static final String DEFAULT_SALTED_AUTHENTICATION_QUERY = "select password, password_salt from users where username = ?";
/**
* The default query used to retrieve the roles that apply to a user.
*/
protected static final String DEFAULT_USER_ROLES_QUERY = "select role_name from user_roles where username = ?";
/**
* The default query used to retrieve permissions that apply to a particular role.
*/
protected static final String DEFAULT_PERMISSIONS_QUERY = "select permission from roles_permissions where role_name = ?";
在数据库中设置与之对应的表
Java代码
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Test;
/**
* JDBCRealm的使用
*/
public class JdbcRealmTest {
DruidDataSource dataSource = new DruidDataSource();
{
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("root");
dataSource.setPassword("root");
}
@Test
public void testAuthentication(){
JdbcRealm jdbcRealm = new JdbcRealm();
jdbcRealm.setDataSource(dataSource);
//1.构建SecurityManager环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(jdbcRealm);
//2.主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("Tom","123123");
subject.login(usernamePasswordToken);
System.out.println(subject.isAuthenticated());
//检验授权
subject.checkRole("Boss");
//subject.checkPermission("user:select");
}
}
试一下自定义SQL吧
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Test;
/**
* JDBCRealm的使用
*/
public class JdbcRealmTest {
DruidDataSource dataSource = new DruidDataSource();
{
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("root");
dataSource.setPassword("root");
}
@Test
public void testAuthentication(){
JdbcRealm jdbcRealm = new JdbcRealm();
jdbcRealm.setDataSource(dataSource);
//默认为false
jdbcRealm.setPermissionsLookupEnabled(true);
String sql = "select password from test_user where user_name = ?";
jdbcRealm.setAuthenticationQuery(sql);
String roleSql = "select role_name from test_user_role where user_name = ?";
jdbcRealm.setUserRolesQuery(roleSql);
//1.构建SecurityManager环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(jdbcRealm);
//2.主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
//UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("Kelvin","123123");
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("Tom","123123");
subject.login(usernamePasswordToken);
System.out.println(subject.isAuthenticated());
//检验授权
subject.checkRole("Boss");
//subject.checkPermission("user:select");
}
}
4.自定义Realm
CustomRealm.java
package com.winning.shiro.realm;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
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 java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class CustomRealm extends AuthorizingRealm {
Map<String,String> userMap = new HashMap<String,String>(16);
{
userMap.put("Kelvin","123123");
super.setName("customRealm");
}
//授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String userName = (String) principals.getPrimaryPrincipal();
//从数据库或者缓存中获取角色数据
Set<String> roles = getRolesByUserName(userName);
Set<String> permissionInfo = getPermissionByUserName(userName);
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.setStringPermissions(permissionInfo);
simpleAuthorizationInfo.setRoles(roles);
return simpleAuthorizationInfo;
}
/**
* 模拟数据库
* @return
*/
private Set<String> getPermissionByUserName(String userName){
Set<String> sets = new HashSet<String>();
sets.add("user:delete");
sets.add("user:add");
return sets;
}
private Set<String> getRolesByUserName(String userName) {
Set<String> sets = new HashSet<String>();
sets.add("admin");
sets.add("user");
return sets;
}
//认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//1.从主体传过来的认证信息中,获得用户名
String username = (String) token.getPrincipal();
//2.通过用户名到数据库中获取凭证
String password = getPasswordByUserName(username);
if (password == null){
return null;
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo("Kelvin",password,"customRealm");
return authenticationInfo;
}
/**
* 模拟数据库查询凭证
* @param userName
* @return
*/
private String getPasswordByUserName(String userName){
return userMap.get(userName);
}
}
调用自定义Realm
import com.winning.shiro.realm.CustomRealm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.junit.Test;
public class CustomRealmTest {
@Test
public void testAuthentication(){
CustomRealm customRealm = new CustomRealm();
//1.构建SecurityManager环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(customRealm);
//2.主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("Kelvin","123123");
subject.login(usernamePasswordToken);
//检验认证
System.out.println(subject.isAuthenticated());
//检验授权
subject.checkRole("admin");
subject.checkPermission("user:delete");
}
}
总结Shiro认证授权流程: