1.shiro框架的使用

1.shiro4中pom.xml中进行相应的配置

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-ehcache</artifactId>
        <version>1.4.0</version>
    </dependency>

    <!--        1-->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>1.4.1</version>
    </dependency>
    <dependency>
        <groupId>com.github.theborakompanioni</groupId>
        <artifactId>thymeleaf-extras-shiro</artifactId>
        <version>2.0.0</version>
    </dependency>

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.1.18</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.1.18</version>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>

    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.1.0</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

2.配置数据库连接
spring:
datasource:
druid:
url: jdbc:mysql://127.0.0.1/db_shior2
driver-class-name: com.mysql.jdbc.Driver
username: root
password: root
initial-size: 1
min-idle: 1
max-active: 20
mybatis:
mapper-locations: classpath:mappers/*Mapper.xml
type-aliases-package: com.li.beans
server:
port: 8066

3.首先创建UserMapper.xml、其次创建UserDao接口

<?xml version="1.0" encoding="UTF-8" ?>
<!--3.mapper接口中没有方法 ,则xml配置文件无需添加-->
<resultMap id="userMap" type="User">
    <id column="user_id" property="userId"></id>
    <result column="username" property="userName"></result>
    <result column="password" property="userPwd"></result>
    <result column="password_salt" property="pwdSalt"></result>
</resultMap>
<select id="queryUserByUserName" resultMap="userMap">
    select  * from tb_users
    where username = #{username}
</select>

4.创建UserDaoTest对象
import com.li.LiApplication;
import com.li.beans.User;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

import static org.junit.Assert.;
/

  • @SpringBootTest(classes= LiApplication.class)

  • 启动类扫描@MapperScan(basePackages = “com.li.dao”)

  • 才能注入userDao

  • @RunWith(SpringRunner.class)加junit4进行测试

  • */
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes= LiApplication.class)
    public class UserDaoTest {

    @Resource
    private UserDao userDao;
    //使用junit4进行测试
    @org.junit.Test
    public void queryUserByUserName() throws Exception {
    User user = userDao.queryUserByUserName(“zhangsan”);
    System.out.println(user);
    }
    }

5.主启动类中进行如下配置
@EnableCaching
@SpringBootApplication
@MapperScan(basePackages = “com.li.dao”)
public class LiApplication {

public static void main(String[] args) {
    SpringApplication.run(LiApplication.class, args);
}

}

6.UserDaoTest类中添加如下配置
@Resource
private UserDao userDao;

7.首先创建RoleMapper.xml

<?xml version="1.0" encoding="UTF-8" ?> SELECT role_name FROM tb_users INNER JOIN tb_urs on tb_users.users_id=tb_urs.uid INNER JOIN tb_roles on tb_urs.rid=tb_roles.role_id where tb_users.username=#{username}

8.创建RoleDao
public interface RoleDao {

public Set<String>  queryRoleNameByUserName(String username) ;

}

9.创建RoleDaoTest
@RunWith(SpringRunner.class)
@SpringBootTest(classes = LiApplication.class)
public class RoleDaoTest {

@Resource
private RoleDao roleDao;
@Test
public void queryRoleNameByUserName() throws Exception {
    Set<String> roleNames =  roleDao.queryRoleNameByUserName("lisi");
    Iterator<String> iterator = roleNames.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
}

}

10.首先创建PermissionMapper.xml、其次创建PerssionMapperDao接口

<?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
SELECT tb_permissions.permission_code FROM tb_users INNER JOIN tb_urs on tb_users.users_id=tb_urs.uid INNER JOIN tb_roles on tb_urs.rid=tb_roles.role_id INNER JOIN tb_rps on tb_roles.role_id=tb_rps.rid INNER JOIN tb_permissions on tb_rps.pid=tb_permissions.permission_id WHERE tb_users.username=#{username}
</select>

11.创建PermissionDaoTest
@RunWith(SpringRunner.class)
@SpringBootTest(classes = LiApplication.class)
public class PermissionDaoTest {

@Resource
private PermissionDao PermissionDao;
@Test
public void queryPermissionByUsername() throws Exception {
    Set<String> ps = PermissionDao.queryPermissionByUsername("lisi");
    Iterator<String> it = ps.iterator();
    while (it.hasNext()){
        System.out.println(it.next());
    }
}

}

12.进行权限配置
a. 获取认证安全数据、创建MyRealm、用户通过subject.login()登录之后调用此方法doGetAuthenticationInfo、最后把AuthenticationToken对象传递给principalCollection对象、然后从相应的对象之中获取用户名、然后查询权限列表
public class MyRealm extends AuthorizingRealm {
@Resource
private UserDao userDao;
@Resource
private RoleDao roleDao;
@Resource
private PermissionDao permissionDao;

    public String getName(){
        return "MyReal";
    }


    /*
     * 获取授权的数据(将当前用户的角色及权限查询出来)
     * */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取用户名
        String username = (String) principalCollection.iterator().next();
        //根据用户名获取角色列表
        Set<String> roleNames = roleDao.queryRoleNameByUserName(username);
        //根据用户名获取权限列表
        Set<String> ps = permissionDao.queryPermissionByUsername(username);
        System.out.println("查询权限信息");
        //封装该用户的角色信息和权限信息并返回
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setRoles(roleNames);
        info.setStringPermissions(ps);

        return info;
}

/*

  • 获取认证的安全数据

  • */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    //authenticationToken就是subject.login(token)的token
    UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
    String username = token.getUsername();
    //根据用户名查询密码
    User user = userDao.queryUserByUserName(username);
    //多态写法封装对应的写法返回AuthenticationInfo、AuthenticationInfo传给principalCollection
    // AuthenticationInfo info = new SimpleAuthenticationInfo(
    // username,
    // user.getUserPwd(),
    // getName()
    // );
    //如加密加盐之后ByteSource.Util.bytes(user.getUserPwd()),
    //23.ByteSource.Util.bytes(user.getPwdSalt())认证器知道盐后才能匹配
    AuthenticationInfo info = new SimpleAuthenticationInfo(
    username,
    user.getUserPwd(),
    ByteSource.Util.bytes(user.getPwdSalt()),
    getName()
    );
    return info;
    }
    }

    b.showConfig类中通过过滤器设置权限如下
    filterMapper.put("/c_add.html",“perms[sys:c:save]”);
    c. 已注解的方式设置其权限
    CustomerController中设置权限
    @RequiresPermissions(“sys:k:find”)只用拥有该权限才能调用这个方法
    d.CustimerControlle.class中自定义的权限
    Subject subject = SecurityUtils.getSubject();
    if(subject.isPermitted(“sys:k:find”)){
    return “customer_list”;
    }
    System.out.println("--------->查询客户信息");
    return “lesspermission”;
    }
    e. ShowConfig中进行配置
    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator(){
    DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
    defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
    return defaultAdvisorAutoProxyCreator;
    }
    @Bean
    public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager defaultWebSecurityManager){
    AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor =
    new AuthorizationAttributeSourceAdvisor();
    authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager);
    return authorizationAttributeSourceAdvisor;

    }

13.密码加密操作
a.创建UserServeiceImpl类
public void checkLogin(String username,String password,boolean rememberme) throws Exception{
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
token.setRememberMe(rememberme);
subject.login(token);
}
b.

c.
@RequestMapping(“regist”)
public String regist(String username,String password){
System.out.println(“注册”);
//注册时对密码加密存储
Md5Hash md5Hash = new Md5Hash(password);
System.out.println("---->"+md5Hash.toHex());

    //加盐加密
    int num = new Random().nextInt(90000)+10000;
    Md5Hash md5Hash1 = new Md5Hash(password,num+"");
    System.out.println(num+"---->"+md5Hash1.toHex());

    //加盐加密多次hash
    Md5Hash md5Hash2 = new Md5Hash(password,num+"",3);
    System.out.println("---->"+md5Hash2);

    //更牛hash

// SimpleHash simpleHash = new SimpleHash(“md5”,password,num+"",3);
// System.out.println(simpleHash.toHex());
return “login”;
}

d.添加regist.html

账号:

<p>
    密码:<input type=" text" name="password">
</p>
<input type="submit" value="提交注册">
f. @Bean//指定加密规则 public HashedCredentialsMatcher getHashedCredentialsMatcher(){ //matcher就是用来指定加密规则的 HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(); //加密方式 matcher.setHashAlgorithmName("md5"); //hash次数,如果加盐加密hash次数是多次则将hash次数进行改变 matcher.setHashIterations(1); return matcher; }
配置自定义Relam,myRealm.setCredentialsMatcher(matcher)加密工具给relam
@Bean
public MyRealm getMyRelam(HashedCredentialsMatcher matcher){
    MyRealm myRealm = new MyRealm();
    myRealm.setCredentialsMatcher(matcher);
    return  myRealm;
}

然后交给最后把MyRealem交给安全管理器
securityManager.setRealm(myRealm);

如果有盐则在MyRealm中的protected AuthenticationInfo doGetAuthenticationInfo中添加
AuthenticationInfo info = new SimpleAuthenticationInfo(
username,
user.getUserPwd(),
ByteSource.Util.bytes(user.getPwdSalt()),
getName()
);
添加盐加密规则 ByteSource.Util.bytes(user.getPwdSalt()),

14.缓存操作
添加缓存依赖包

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-ehcache</artifactId>
        <version>1.4.0</version>
    </dependency>

a.index.html中添加如下操作.<shiro:hasPermission name=“sys:c:save”>

入库
</shiro:hasPermission>
b.添加缓存配置文件ehcach1.xmls

<?xml version="1.0" encoding="utf-8" ?>

c.ShowConfig中添加如下配置
/*
*25.切记缓存文件不能是ehcache.xml

  • 1.ehCacheManager.setCacheManagerConfigFile(“classpath:ehcache.xml”);设置缓存配置文件

    1. securityManager.setRealm(myRealm);缓存管理器交给securityManager
  • */

    public EhCacheManager EhCacheManager(){
    EhCacheManager ehCacheManager = new EhCacheManager();
    ehCacheManager.setCacheManagerConfigFile(“classpath:ehcache1.xml”);
    return ehCacheManager;
    }
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(MyRealm myRealm){
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setRealm(myRealm);
    securityManager.setCacheManager(EhCacheManager());
    securityManager.setSessionManager(getDefaultWebSessionManager());
    securityManager.setRememberMeManager(getCookieRememberMeManager());
    return securityManager;
    }
    /*
    15.设置记住我
    解释:登录时没有记住我,关闭浏览器之后,不可直接访问主界面,记住我则反之
    a.登录后给后端控制器传入remenberme状态信息
    @RequestMapping(“login”)
    public String login(String username,String password,boolean remenberme){
    try {
    //26.传入remenberme参数
    userService.checkLogin(username,password,remenberme);
    System.out.println(“登录成功”);
    return “index”;
    }catch (Exception e){
    System.out.println(“登录失败”);

          return "login";
      }
    

    }
    d.UserServiceImple.class编写如下方法

    设置状态信息
    public void checkLogin(String username,String password,boolean rememberme) throws Exception{
    Subject subject = SecurityUtils.getSubject();
    UsernamePasswordToken token = new UsernamePasswordToken(username,password);
    token.setRememberMe(rememberme);
    subject.login(token);
    }
    b.ShowConfig中设置
    public CookieRememberMeManager getCookieRememberMeManager(){
    CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
    SimpleCookie cookie = new SimpleCookie(“rememberMe”);
    cookie.setMaxAge(302460*60);
    rememberMeManager.setCookie(cookie);
    return rememberMeManager;
    }
    c.加入到security中
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(MyRealm myRealm){
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setRememberMeManager(getCookieRememberMeManager());
    return securityManager;
    }

16.多Realm
解释:

  • 多realm的链式结构,用户名第一个realm中没有找到用户名和密码则会在第二个realm中找相应的用户名或者密码

  • 第一个找到用户名和密码也会找第二个
    a.自定义manageRealm
    public class ManageRealm extends AuthorizingRealm {

    Logger log = LoggerFactory.getLogger(ManageRealm.class);
    @Override
    public String getName(){
    return “ManageRealm”;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

      UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
      log.info("--------------------------->ManageRealm");
      String username = token.getUsername();
      SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, "222222", getName());
      return info;
    

    }
    }
    b.自定义UserRealm
    public class UserRealm extends AuthorizingRealm {

    Logger logger = LoggerFactory.getLogger(UserRealm.class);
    @Override
    public String getName(){
    return “UserRealm”;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    logger.info("--------------->UserRealm");
    UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
    String username = token.getUsername();
    SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, “123456”, getName());
    return info;
    }
    }

c.ShiroConfig中进行相应的配置
public DefaultWebSecurityManager getDefaultWebSecurityManager(){
realms.add(userRealm());
realms.add(manageRealm());
securityManager.setRealms(realms);
return securityManager;
}
2.实现Realm并发结构
设置登录类型进行登录后,根据类型返回指定的realm
a.自定义Mytoken,重写UserNamePassword
public class Mytoken extends UsernamePasswordToken {
private String loginToken;

public Mytoken(String username,String password,String loginToken){
    super(username, password);
    this.loginToken = loginToken;
}


public String getLoginToken() {
    return loginToken;
}

public void setLoginToken(String loginToken) {
    this.loginToken = loginToken;
}

}

a.自定义认证器、重写认证方法
自定义认证器
public class MyModularRealmAuthenticator extends ModularRealmAuthenticator {

Logger logger = LoggerFactory.getLogger(MyModularRealmAuthenticator.class);


@Override
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
    logger.info("<-----------MyModularRealmAuthentication------------->");
    this.assertRealmsConfigured();
    //获得所有的Realm
    Collection<Realm> realms = this.getRealms();
    //自定义token
    Mytoken token = (Mytoken) authenticationToken;

    String loginToken = token.getLoginToken();
    Collection<Realm> typeRealms=new ArrayList<>();
    //输出realms中的Realm根据条件保存相应的Realm到typeRealms
    for (Realm realm : realms) {
        if(realm.getName().startsWith(loginToken)){
            typeRealms.add(realm);
        }
    }

    if(typeRealms.size()==1) {
        //访问当个的realm
        return this.doSingleRealmAuthentication((Realm) typeRealms.iterator().next(), authenticationToken);
    }else{
        //typeRealms这里传递的参数就是最终访问的realm
        return  this.doMultiRealmAuthentication(typeRealms,authenticationToken);
    }

}

}
b.相应的UserController中进行相应的设置
public class UserController {
Logger logger = LoggerFactory.getLogger(UserController.class);

@RequestMapping("login")
public String login(String username,String password,String loginType){
    logger.info("------------------------>UserController");

    try {

// UsernamePasswordToken token = new UsernamePasswordToken(username, password);
Mytoken mytoken = new Mytoken(username,password,loginType);
Subject subject = SecurityUtils.getSubject();
subject.login(mytoken);
return “index”;
}catch (Exception e){
return “login”;
}
}
}

b.ShiroConfig中自定义认证器交给spring容器
public MyModularRealmAuthenticator getMyModularRealmAuthenticator(){
MyModularRealmAuthenticator realmAuthenticator = new MyModularRealmAuthenticator();
return realmAuthenticator;
}

@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

    securityManager.setAuthenticator(getMyModularRealmAuthenticator());
    Collection<Realm> realms =new ArrayList<>();
    realms.add(userRealm());
    realms.add(manageRealm());
    securityManager.setRealms(realms);
    return securityManager;
}

注意(shiro4+shiro5框架demo)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SLF4J: No SLF4J providers were found. SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details. Exception in thread "main" org.apache.shiro.config.ConfigurationException: Unable to instantiate class [org.apache.shiro.web.mgt.DefaultWebSecurityManager] for object named 'securityManager'. Please ensure you've specified the fully qualified class name correctly. at org.apache.shiro.config.ReflectionBuilder.createNewInstance(ReflectionBuilder.java:309) at org.apache.shiro.config.ReflectionBuilder$InstantiationStatement.doExecute(ReflectionBuilder.java:927) at org.apache.shiro.config.ReflectionBuilder$Statement.execute(ReflectionBuilder.java:887) at org.apache.shiro.config.ReflectionBuilder$BeanConfigurationProcessor.execute(ReflectionBuilder.java:765) at org.apache.shiro.config.ReflectionBuilder.buildObjects(ReflectionBuilder.java:260) at org.apache.shiro.config.IniSecurityManagerFactory.buildInstances(IniSecurityManagerFactory.java:167) at org.apache.shiro.config.IniSecurityManagerFactory.createSecurityManager(IniSecurityManagerFactory.java:130) at org.apache.shiro.config.IniSecurityManagerFactory.createSecurityManager(IniSecurityManagerFactory.java:108) at org.apache.shiro.config.IniSecurityManagerFactory.createInstance(IniSecurityManagerFactory.java:94) at org.apache.shiro.config.IniSecurityManagerFactory.createInstance(IniSecurityManagerFactory.java:46) at org.apache.shiro.config.IniFactorySupport.createInstance(IniFactorySupport.java:123) at org.apache.shiro.util.AbstractFactory.getInstance(AbstractFactory.java:47) at com.xiu.Quickstart.main(Quickstart.java:26) Caused by: org.apache.shiro.util.UnknownClassException: Unable to load class named [org.apache.shiro.web.mgt.DefaultWebSecurityManager] from the thread context, current, or system/application ClassLoaders. All heuristics have been exhausted. Class could not be found. at org.apache.shiro.util.ClassUtils.forName(ClassUtils.java:152) at org.apache.shiro.util.ClassUtils.newInstance(ClassUtils.java:168) at org.apache.shiro.config.ReflectionBuilder.createNewInstance(ReflectionBuilder.java:302) ... 12 more
06-10

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值